

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/boshi.jpeg">
  <link rel="icon" type="image/png" href="/img/boshi.jpeg">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="wangpf">
  <meta name="keywords" content="">
  <title>Node基础总结 - wpf的博客</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/foundation.min.css" />
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_6peoq002giu.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_pjno9b9zyxs.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.1.1"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>Wangpf's blog</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/img/article.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container page-header text-center fade-in-up">
            <span class="h2" id="subtitle">
              
            </span>

            
              
  <div class="mt-3 post-meta">
    <i class="iconfont icon-date-fill" aria-hidden="true"></i>
    <time datetime="2020-08-18 17:30" pubdate>
      2020年8月18日 下午
    </time>
  </div>


<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      11.7k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      155
       分钟
    </span>
  

  
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto" id="post">
            <!-- SEO header -->
            <h1 style="display: none">Node基础总结</h1>
            
            <div class="markdown-body" id="post-body">
              <h2 id="为什么要学习Node-js"><a href="#为什么要学习Node-js" class="headerlink" title="为什么要学习Node.js"></a>为什么要学习Node.js</h2><ul>
<li>企业需求<ul>
<li>具有服务端开发经验更改</li>
<li>front-end</li>
<li>back-end</li>
<li>全栈开发工程师</li>
<li>基本的网站开发能力<ul>
<li>服务端</li>
<li>前端</li>
<li>运维部署</li>
</ul>
</li>
<li>多人社区</li>
</ul>
</li>
</ul>
<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200317114503403.png" srcset="/img/loading.gif" alt="image-20200317114503403"></p>
<h2 id="Node-js是什么"><a href="#Node-js是什么" class="headerlink" title="Node.js是什么"></a>Node.js是什么</h2><ul>
<li>Node.js是JavaScript 运行时</li>
<li>通俗易懂的讲，Node.js是JavaScript的运行平台</li>
<li>Node.js既不是语言，也不是框架，它是一个平台</li>
<li>浏览器中的JavaScript<ul>
<li>EcmaScript<ul>
<li>基本语法</li>
<li>if</li>
<li>var</li>
<li>function</li>
<li>Object</li>
<li>Array</li>
</ul>
</li>
<li>Bom</li>
<li>Dom</li>
</ul>
</li>
<li>Node.js中的JavaScript<ul>
<li>没有Bom，Dom</li>
<li>EcmaScript</li>
<li>在Node中这个JavaScript执行环境为JavaScript提供了一些服务器级别的API<ul>
<li>例如文件的读写</li>
<li>网络服务的构建</li>
<li>网络通信</li>
<li>http服务器</li>
</ul>
</li>
</ul>
</li>
<li>构建与Chrome的V8引擎之上<ul>
<li>代码只是具有特定格式的字符串</li>
<li>引擎可以认识它，帮你解析和执行</li>
<li>Google Chrome的V8引擎是目前公认的解析执行JavaScript代码最快的</li>
<li>Node.js的作者把Google Chrome中的V8引擎移植出来，开发了一个独立的JavaScript运行时环境</li>
</ul>
</li>
<li>Node.js uses an envent-driven,non-blocking I/O mode that makes it lightweight and efficent.<ul>
<li>envent-driven    事件驱动</li>
<li>non-blocking I/O mode   非阻塞I/O模型（异步）</li>
<li>ightweight and efficent.   轻量和高效</li>
</ul>
</li>
<li>Node.js package ecosystem,npm,is the larget scosystem of open sourcr libraries in the world<ul>
<li>npm 是世界上最大的开源生态系统</li>
<li>绝大多数JavaScript相关的包都存放在npm上，这样做的目的是为了让开发人员更方便的去下载使用</li>
<li>npm install jquery</li>
</ul>
</li>
</ul>
<h2 id="Node能做什么"><a href="#Node能做什么" class="headerlink" title="Node能做什么"></a>Node能做什么</h2><ul>
<li>web服务器后台</li>
<li>命令行工具<ul>
<li>npm(node)</li>
<li>git(c语言)</li>
<li>hexo（node）</li>
<li>…</li>
</ul>
</li>
<li>对于前端工程师来讲，接触最多的是它的命令行工具<ul>
<li>自己写的很少，主要是用别人第三方的</li>
<li>webpack</li>
<li>gulp</li>
<li>npm</li>
</ul>
</li>
</ul>
<h1 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h1><h2 id="安装Node环境"><a href="#安装Node环境" class="headerlink" title="安装Node环境"></a>安装Node环境</h2><ul>
<li>查看Node环境的版本号</li>
<li>下载：<a target="_blank" rel="noopener" href="https://nodejs.org/en/">https://nodejs.org/en/</a></li>
<li>安装：<ul>
<li>傻瓜式安装，一路<code>next</code></li>
<li>安装过再次安装会升级</li>
</ul>
</li>
<li>确认Node环境是否安装成功<ul>
<li>查看node的版本号：<code>node --version</code></li>
<li>或者<code>node -v</code></li>
</ul>
</li>
<li>配置环境变量</li>
</ul>
<h2 id="解析执行JavaScript"><a href="#解析执行JavaScript" class="headerlink" title="解析执行JavaScript"></a>解析执行JavaScript</h2><ol>
<li>创建编写JavaScript脚本文件</li>
<li>打开终端，定位脚本文件的所属目录</li>
<li>输入<code>node  文件名</code>执行对应的文件</li>
</ol>
<p>注意：文件名不要用<code>node.js</code>来命名，也就是说除了<code>node</code>这个名字随便起，最好不要使用中文。</p>
<h2 id="文件的读写"><a href="#文件的读写" class="headerlink" title="文件的读写"></a>文件的读写</h2><p>文件读取:</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">//浏览器中的JavaScript是没有文件操作能力的</span>
<span class="hljs-comment">//但是Node中的JavaScript具有文件操作能力</span>
<span class="hljs-comment">//fs是file-system的简写，就是文件系统的意思</span>
<span class="hljs-comment">//在Node中如果想要进行文件的操作就必须引用fs这个核心模块</span>
<span class="hljs-comment">//在fs这个核心模块中，就提供了人所有文件操作相关的API</span>
<span class="hljs-comment">//例如 fs.readFile就是用来读取文件的</span>

<span class="hljs-comment">//  1.使用fs核心模块</span>
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);

<span class="hljs-comment">// 2.读取文件</span>
fs.readFile(<span class="hljs-string">&#x27;./data/a.txt&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
   <span class="hljs-keyword">if</span>(err)&#123;
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;文件读取失败&#x27;</span>);
   &#125;
    <span class="hljs-keyword">else</span>&#123;
         <span class="hljs-built_in">console</span>.log(data.toString());
    &#125;
&#125;)</code></pre></div>

<p>文件写入：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">//  1.使用fs核心模块</span>
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);

<span class="hljs-comment">// 2.将数据写入文件</span>
fs.writeFile(<span class="hljs-string">&#x27;./data/a.txt&#x27;</span>,<span class="hljs-string">&#x27;我是文件写入的信息&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
   <span class="hljs-keyword">if</span>(err)&#123;
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;文件写入失败&#x27;</span>);
   &#125;
    <span class="hljs-keyword">else</span>&#123;
         <span class="hljs-built_in">console</span>.log(data.toString());
    &#125;
&#125;)</code></pre></div>

<h2 id="http"><a href="#http" class="headerlink" title="http"></a>http</h2><p>服务器：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 1.加载http核心模块</span>
<span class="hljs-keyword">var</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;http&#x27;</span>);

<span class="hljs-comment">// 2.使用http.createServer()创建一个web服务器</span>
<span class="hljs-keyword">var</span> server = http.createServer();

<span class="hljs-comment">// 3.服务器要做的事儿</span>
<span class="hljs-comment">// 提供服务：对数据服务</span>
<span class="hljs-comment">// 发请求</span>
<span class="hljs-comment">//	接收请求</span>
<span class="hljs-comment">//	处理请求</span>
<span class="hljs-comment">//	反馈（发送响应）</span>
<span class="hljs-comment">//	当客户端请求过来，就会自动触发服务器的request请求事件，然后执行第二个参数：回调处理函数</span>
server.on(<span class="hljs-string">&#x27;request&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;收到客户的请求了&#x27;</span>)
&#125;)

<span class="hljs-comment">// 4.绑定端口号，启动服务</span>
server.listen(<span class="hljs-number">3000</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;runing...&#x27;</span>)
&#125;)
</code></pre></div>

<h1 id="Node中的模块系统"><a href="#Node中的模块系统" class="headerlink" title="Node中的模块系统"></a>Node中的模块系统</h1><p>使用Node编写应用程序主要就是在使用：</p>
<ul>
<li><p>EcmaScript语言</p>
<ul>
<li>和浏览器一样，在Node中没有Bom和Dom</li>
</ul>
</li>
<li><p>核心模块</p>
<ul>
<li>文件操作的fs</li>
<li>http服务操作的http</li>
<li>url路径操作模块</li>
<li>path路径处理模块</li>
<li>os操作系统信息</li>
</ul>
</li>
<li><p>第三方模块</p>
<ul>
<li>art-template</li>
<li>必须通过npm来下载才可以使用</li>
</ul>
</li>
<li><p>自己写的模块</p>
<ul>
<li>自己创建的文件</li>
</ul>
</li>
</ul>
<h2 id="什么是模块化"><a href="#什么是模块化" class="headerlink" title="什么是模块化"></a>什么是模块化</h2><ul>
<li>文件作用域(模块是独立的，在不同的文件使用必须要重新引用)【在node中没有全局作用域，它是文件模块作用域】</li>
<li>通信规则<ul>
<li>加载require</li>
<li>导出exports</li>
</ul>
</li>
</ul>
<h2 id="CommonJS模块规范"><a href="#CommonJS模块规范" class="headerlink" title="CommonJS模块规范"></a>CommonJS模块规范</h2><p>在Node中的JavaScript还有一个重要的概念，模块系统。</p>
<ul>
<li><p>模块作用域</p>
</li>
<li><p>使用require方法来加载模块</p>
</li>
<li><p>使用exports接口对象来导出模板中的成员</p>
<h3 id="加载require"><a href="#加载require" class="headerlink" title="加载require"></a>加载<code>require</code></h3><p>语法：</p>
<div class="hljs"><pre><code class="hljs java"><span class="hljs-keyword">var</span> 自定义变量名 = require(<span class="hljs-string">&#x27;模块&#x27;</span>)</code></pre></div>

<p>作用：</p>
<ul>
<li>执行被加载模块中的代码</li>
<li>得到被加载模块中的<code>exports</code>导出接口对象</li>
</ul>
<h3 id="导出exports"><a href="#导出exports" class="headerlink" title="导出exports"></a>导出<code>exports</code></h3><ul>
<li><p>Node中是模块作用域，默认文件中所有的成员只在当前模块有效</p>
</li>
<li><p>对于希望可以被其他模块访问到的成员，我们需要把这些公开的成员都挂载到<code>exports</code>接口对象中就可以了</p>
<p>导出多个成员（必须在对象中）：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-built_in">exports</span>.a = <span class="hljs-number">123</span>;
<span class="hljs-built_in">exports</span>.b = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;bbb&#x27;</span>)
&#125;;
<span class="hljs-built_in">exports</span>.c = &#123;
    foo:<span class="hljs-string">&quot;bar&quot;</span>
&#125;;
<span class="hljs-built_in">exports</span>.d = <span class="hljs-string">&#x27;hello&#x27;</span>;</code></pre></div>



</li>
</ul>
</li>
</ul>
<div class="hljs"><pre><code>导出单个成员（拿到的就是函数，字符串）：

<pre><code class="hljs javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-string">&#x27;hello&#x27;</span>;</code></pre></div>

以下情况会覆盖：

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-string">&#x27;hello&#x27;</span>;
<span class="hljs-comment">//后者会覆盖前者</span>
<span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">x,y</span>) </span>&#123;
    <span class="hljs-keyword">return</span> x+y;
&#125;</code></pre></div>

也可以通过以下方法来导出多个成员：

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-built_in">module</span>.exports = &#123;
    foo = <span class="hljs-string">&#x27;hello&#x27;</span>,
    add:<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        <span class="hljs-keyword">return</span> x+y;
    &#125;
&#125;;</code></pre></div></code></pre>
<h2 id="模块原理"><a href="#模块原理" class="headerlink" title="模块原理"></a>模块原理</h2><p>exports和<code>module.exports</code>的一个引用：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">exports</span> === <span class="hljs-built_in">module</span>.exports);	<span class="hljs-comment">//true</span>

<span class="hljs-built_in">exports</span>.foo = <span class="hljs-string">&#x27;bar&#x27;</span>;

<span class="hljs-comment">//等价于</span>
<span class="hljs-built_in">module</span>.exports.foo = <span class="hljs-string">&#x27;bar&#x27;</span>;</code></pre></div>

<p><code>当给exports重新赋值后，exports！= module.exports.</code></p>
<p><code>最终return的是module.exports,无论exports中的成员是什么都没用。</code></p>
<div class="hljs"><pre><code class="hljs javascript">真正去使用的时候：
	导出单个成员：<span class="hljs-built_in">exports</span>.xxx = xxx;
	导出多个成员：<span class="hljs-built_in">module</span>.exports 或者 modeule.exports = &#123;&#125;;</code></pre></div>

<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 引用服务</span>
<span class="hljs-keyword">var</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;http&#x27;</span>);
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);
<span class="hljs-comment">// 引用模板</span>
<span class="hljs-keyword">var</span> template = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;art-template&#x27;</span>);
<span class="hljs-comment">// 创建服务</span>
<span class="hljs-keyword">var</span> server = http.createServer();
<span class="hljs-comment">// 公共路径</span>
<span class="hljs-keyword">var</span> wwwDir = <span class="hljs-string">&#x27;D:/app/www&#x27;</span>;
server.on(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, res</span>) </span>&#123;
    <span class="hljs-keyword">var</span> url = req.url;
    <span class="hljs-comment">// 读取文件</span>
    fs.readFile(<span class="hljs-string">&#x27;./template-apche.html&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, data</span>) </span>&#123;
        <span class="hljs-keyword">if</span> (err) &#123;
            <span class="hljs-keyword">return</span> res.end(<span class="hljs-string">&#x27;404 Not Found&#x27;</span>);
        &#125;
        fs.readdir(wwwDir, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, files</span>) </span>&#123;
            <span class="hljs-keyword">if</span> (err) &#123;
                <span class="hljs-keyword">return</span> res.end(<span class="hljs-string">&#x27;Can not find www Dir.&#x27;</span>)
            &#125;
            <span class="hljs-comment">// 使用模板引擎解析替换data中的模板字符串</span>
            <span class="hljs-comment">// 去xmpTempleteList.html中编写模板语法</span>
            <span class="hljs-keyword">var</span> htmlStr = template.render(data.toString(), &#123; 
                title: <span class="hljs-string">&#x27;D:/app/www/ 的索引&#x27;</span>,
                files:files 
            &#125;);
            <span class="hljs-comment">// 发送响应数据</span>
            res.end(htmlStr);
        &#125;)
    &#125;)
&#125;);
server.listen(<span class="hljs-number">3000</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;running....&#x27;</span>);
&#125;)</code></pre></div>

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-number">1.</span>jQuery中的each 和 原生JavaScript方法forEach的区别：
	提供源头：
    	原生js是es5提供的（不兼容IE8）,
        jQuery的each是jQuery第三方库提供的（如果要使用需要用<span class="hljs-number">2</span>以下的版本也就是<span class="hljs-number">1.</span>版本）,它的each方法主要用来遍历jQuery实例对象（伪数组）,同时也可以做低版本forEach的替代品,jQuery的实例对象不能使用forEach方法，如果想要使用必须转为数组（[].slice.call(jQuery实例对象)）才能使用
<span class="hljs-number">2.</span>模块中导出多个成员和导出单个成员
<span class="hljs-number">3.301</span>和<span class="hljs-number">302</span>的区别：
	<span class="hljs-number">301</span>永久重定向,浏览器会记住
    <span class="hljs-number">302</span>临时重定向
<span class="hljs-number">4.</span><span class="hljs-built_in">exports</span>和<span class="hljs-built_in">module</span>.exports的区别:
	每个模块中都有一个<span class="hljs-built_in">module</span>对象
    <span class="hljs-built_in">module</span>对象中有一个<span class="hljs-built_in">exports</span>对象
    我们可以把需要导出的成员都挂载到<span class="hljs-built_in">module</span>.exports接口对象中
	也就是<span class="hljs-string">`module.exports.xxx = xxx`</span>的方式
    但是每次写太多了就很麻烦，所以Node为了简化代码，就在每一个模块中都提供了一个成员叫<span class="hljs-string">`exports`</span>
    <span class="hljs-string">`exports === module.exports`</span>结果为<span class="hljs-literal">true</span>,所以完全可以<span class="hljs-string">`exports.xxx = xxx`</span>
    当一个模块需要导出单个成员的时候必须使用<span class="hljs-string">`module.exports = xxx`</span>的方式，=,使用<span class="hljs-string">`exports = xxx`</span>不管用,因为每个模块最终<span class="hljs-keyword">return</span>的是<span class="hljs-built_in">module</span>.exports,而<span class="hljs-built_in">exports</span>只是<span class="hljs-built_in">module</span>.exports的一个引用,所以<span class="hljs-string">`exports`</span>即使重新赋值,也不会影响<span class="hljs-string">`module.exports`</span>。
    有一种赋值方式比较特殊：<span class="hljs-string">`exports = module.exports`</span>这个用来新建立引用关系的。</code></pre></div>

<h1 id="require的加载规则"><a href="#require的加载规则" class="headerlink" title="require的加载规则"></a>require的加载规则</h1><ul>
<li><p>核心模块</p>
<ul>
<li>模块名</li>
</ul>
</li>
<li><p>第三方模块</p>
<ul>
<li>模块名</li>
</ul>
</li>
<li><p>用户自己写的</p>
<ul>
<li>路径</li>
</ul>
</li>
</ul>
<h2 id="require的加载规则："><a href="#require的加载规则：" class="headerlink" title="require的加载规则："></a>require的加载规则：</h2><ul>
<li><p>优先从缓存加载</p>
</li>
<li><p>判断模块标识符</p>
<ul>
<li>核心模块</li>
<li>自己写的模块（路径形式的模块）</li>
<li>第三方模块（node_modules）<ul>
<li>第三方模块的标识就是第三方模块的名称（不可能有第三方模块和核心模块的名字一致）</li>
<li>npm<ul>
<li>开发人员可以把写好的框架库发布到npm上</li>
<li>使用者通过npm命令来下载</li>
</ul>
</li>
<li>使用方式：<code>var 名称 = require(&#39;npm install【下载包】 的包名&#39;)</code><ul>
<li>node_modules/express/package.json main</li>
<li>如果package.json或者main不成立，则查找被选择项：index.js</li>
<li>如果以上条件都不满足，则继续进入上一级目录中的node_modules按照上面的规则依次查找，直到当前文件所属此盘根目录都找不到最后报错</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 如果非路径形式的标识</span>
<span class="hljs-comment">// 路径形式的标识：</span>
    <span class="hljs-comment">// ./  当前目录 不可省略</span>
    <span class="hljs-comment">// ../  上一级目录  不可省略</span>
    <span class="hljs-comment">//  /xxx也就是D:/xxx</span>
    <span class="hljs-comment">// 带有绝对路径几乎不用（D:/a/foo.js）</span>
<span class="hljs-comment">// 首位表示的是当前文件模块所属磁盘根目录</span>
<span class="hljs-comment">// require(&#x27;./a&#x27;); </span>


<span class="hljs-comment">// 核心模块</span>
<span class="hljs-comment">// 核心模块本质也是文件，核心模块文件已经被编译到了二进制文件中了，我们只需要按照名字来加载就可以了</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>); 

<span class="hljs-comment">// 第三方模块</span>
<span class="hljs-comment">// 凡是第三方模块都必须通过npm下载（npm i node_modules），使用的时候就可以通过require(&#x27;包名&#x27;)来加载才可以使用</span>
<span class="hljs-comment">// 第三方包的名字不可能和核心模块的名字是一样的</span>
<span class="hljs-comment">// 既不是核心模块，也不是路径形式的模块</span>
<span class="hljs-comment">//      先找到当前文所述目录的node_modules</span>
<span class="hljs-comment">//      然后找node_modules/art-template目录</span>
<span class="hljs-comment">//      node_modules/art-template/package.json</span>
<span class="hljs-comment">//      node_modules/art-template/package.json中的main属性</span>
<span class="hljs-comment">//      main属性记录了art-template的入口模块</span>
<span class="hljs-comment">//      然后加载使用这个第三方包</span>
<span class="hljs-comment">//      实际上最终加载的还是文件</span>

<span class="hljs-comment">//      如果package.json不存在或者mian指定的入口模块不存在</span>
<span class="hljs-comment">//      则node会自动找该目录下的index.js</span>
<span class="hljs-comment">//      也就是说index.js是一个备选项，如果main没有指定，则加载index.js文件</span>
<span class="hljs-comment">//      </span>
        <span class="hljs-comment">// 如果条件都不满足则会进入上一级目录进行查找</span>
<span class="hljs-comment">// 注意：一个项目只有一个node_modules，放在项目根目录中，子目录可以直接调用根目录的文件</span>
<span class="hljs-keyword">var</span> template = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;art-template&#x27;</span>);
</code></pre></div>

<h2 id="模块标识符中的-和文件操作路径中的"><a href="#模块标识符中的-和文件操作路径中的" class="headerlink" title="模块标识符中的/和文件操作路径中的/"></a>模块标识符中的<code>/</code>和文件操作路径中的<code>/</code></h2><p>文件操作路径：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 咱们所使用的所有文件操作的API都是异步的</span>
<span class="hljs-comment">// 就像ajax请求一样</span>
<span class="hljs-comment">// 读取文件</span>
<span class="hljs-comment">// 文件操作中 ./ 相当于当前模块所处磁盘根目录</span>
<span class="hljs-comment">// ./index.txt    相对于当前目录</span>
<span class="hljs-comment">// /index.txt    相对于当前目录</span>
<span class="hljs-comment">// /index.txt   绝对路径,当前文件模块所处根目录</span>
<span class="hljs-comment">// d:express/index.txt   绝对路径</span>
fs.readFile(<span class="hljs-string">&#x27;./index.txt&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
    <span class="hljs-keyword">if</span>(err)&#123;
       <span class="hljs-keyword">return</span>  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;读取失败&#x27;</span>);
    &#125;
    <span class="hljs-built_in">console</span>.log(data.toString());
&#125;)</code></pre></div>

<p>模块操作路径：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 在模块加载中，相对路径中的./不能省略</span>
<span class="hljs-comment">// 这里省略了.也是磁盘根目录</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./index&#x27;</span>)(<span class="hljs-string">&#x27;hello&#x27;</span>)</code></pre></div>



<h1 id="npm"><a href="#npm" class="headerlink" title="npm"></a>npm</h1><ul>
<li>node package manage(node包管理器)</li>
<li>通过npm命令安装jQuery包（npm install –save jquery），在安装时加上–save会主动生成说明书文件信息（将安装文件的信息添加到package.json里面）</li>
</ul>
<h3 id="npm网站"><a href="#npm网站" class="headerlink" title="npm网站"></a>npm网站</h3><blockquote>
<p>​    npmjs.com    网站   是用来搜索npm包的</p>
</blockquote>
<h3 id="npm命令行工具"><a href="#npm命令行工具" class="headerlink" title="npm命令行工具"></a>npm命令行工具</h3><p>npm是一个命令行工具，只要安装了node就已经安装了npm。</p>
<p>npm也有版本概念，可以通过<code>npm --version</code>来查看npm的版本</p>
<p>升级npm(自己升级自己)：</p>
<div class="hljs"><pre><code class="hljs javascript">npm install --<span class="hljs-built_in">global</span> npm</code></pre></div>

<h3 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h3><ul>
<li>npm init(生成package.json说明书文件)<ul>
<li>npm init -y(可以跳过向导，快速生成)</li>
</ul>
</li>
<li>npm install<ul>
<li>一次性把dependencies选项中的依赖项全部安装</li>
<li>简写（npm i）</li>
</ul>
</li>
<li>npm install 包名<ul>
<li>只下载</li>
<li>简写（npm i 包名）</li>
</ul>
</li>
<li>npm install –save 包名<ul>
<li>下载并且保存依赖项（package.json文件中的dependencies选项）</li>
<li>简写（npm i  包名）</li>
</ul>
</li>
<li>npm uninstall 包名<ul>
<li>只删除，如果有依赖项会依然保存</li>
<li>简写（npm un 包名）</li>
</ul>
</li>
<li>npm uninstall –save 包名<ul>
<li>删除的同时也会把依赖信息全部删除</li>
<li>简写（npm un 包名）</li>
</ul>
</li>
<li>npm help<ul>
<li>查看使用帮助</li>
</ul>
</li>
<li>npm 命令 –help<ul>
<li>查看具体命令的使用帮助（npm uninstall –help）</li>
</ul>
</li>
</ul>
<h3 id="解决npm被墙问题"><a href="#解决npm被墙问题" class="headerlink" title="解决npm被墙问题"></a>解决npm被墙问题</h3><p>npm存储包文件的服务器在国外，有时候会被墙，速度很慢，所以需要解决这个问题。</p>
<blockquote>
<p><a target="_blank" rel="noopener" href="https://developer.aliyun.com/mirror/NPM?from=tnpm%E6%B7%98%E5%AE%9D%E7%9A%84%E5%BC%80%E5%8F%91%E5%9B%A2%E9%98%9F%E6%8A%8Anpm%E5%9C%A8%E5%9B%BD%E5%86%85%E5%81%9A%E4%BA%86%E4%B8%80%E4%B8%AA%E9%95%9C%E5%83%8F%EF%BC%88%E4%B9%9F%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E5%A4%87%E4%BB%BD%EF%BC%89%E3%80%82">https://developer.aliyun.com/mirror/NPM?from=tnpm淘宝的开发团队把npm在国内做了一个镜像（也就是一个备份）。</a></p>
</blockquote>
<p>安装淘宝的cnpm：</p>
<div class="hljs"><pre><code class="hljs javascript">npm install -g cnpm --registry=https:<span class="hljs-comment">//registry.npm.taobao.org;</span></code></pre></div>



<div class="hljs"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">在任意目录执行都可以</span>
<span class="hljs-meta">#</span><span class="bash">--global表示安装到全局，而非当前目录</span>
<span class="hljs-meta">#</span><span class="bash">--global不能省略，否则不管用</span>
npm install --global cnpm</code></pre></div>

<p>安装包的时候把以前的<code>npm</code>替换成<code>cnpm</code>。</p>
<div class="hljs"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">走国外的npm服务器下载jQuery包，速度比较慢</span>
npm install jQuery;

<span class="hljs-meta">#</span><span class="bash">使用cnpm就会通过淘宝的服务器来下载jQuery</span>
cnpm install jQuery;</code></pre></div>

<p>如果不想安装<code>cnpm</code>又想使用淘宝的服务器来下载：</p>
<div class="hljs"><pre><code class="hljs shell">npm install jquery --registry=https://npm.taobao.org;</code></pre></div>

<p>但是每次手动加参数就很麻烦，所以我们可以把这个选项加入到配置文件中：</p>
<div class="hljs"><pre><code class="hljs shell">npm config set registry https://npm.taobao.org;

<span class="hljs-meta">#</span><span class="bash">查看npm配置信息</span>
npm config list;</code></pre></div>

<p>只要经过上面的配置命令，则以后所有的<code>npm install</code>都会通过淘宝的服务器来下载</p>
<h1 id="package-json"><a href="#package-json" class="headerlink" title="package.json"></a>package.json</h1><p>每一个项目都要有一个<code>package.json</code>文件（包描述文件，就像产品的说明书一样）</p>
<p>这个文件可以通过<code>npm init</code>自动初始化出来</p>
<div class="hljs"><pre><code class="hljs javascript">
D:\code\node中的模块系统&gt;npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See <span class="hljs-string">`npm help json`</span> <span class="hljs-keyword">for</span> definitive documentation on these fields
and exactly what they <span class="hljs-keyword">do</span>.

Use <span class="hljs-string">`npm install &lt;pkg&gt;`</span> afterwards to install a package and
save it <span class="hljs-keyword">as</span> a dependency <span class="hljs-keyword">in</span> the package.json file.

Press ^C at any time to quit.
package name: (node中的模块系统)
Sorry, name can only contain URL-friendly characters.
package name: (node中的模块系统) cls
version: (<span class="hljs-number">1.0</span><span class="hljs-number">.0</span>)
description: 这是一个测试项目
entry point: (main.js)
test command:
git repository:
keywords:
author: xiaochen
license: (ISC)
About to write to D:\code\node中的模块系统\package.json:

&#123;
  <span class="hljs-string">&quot;name&quot;</span>: <span class="hljs-string">&quot;cls&quot;</span>,
  <span class="hljs-string">&quot;version&quot;</span>: <span class="hljs-string">&quot;1.0.0&quot;</span>,
  <span class="hljs-string">&quot;description&quot;</span>: <span class="hljs-string">&quot;这是一个测试项目&quot;</span>,
  <span class="hljs-string">&quot;main&quot;</span>: <span class="hljs-string">&quot;main.js&quot;</span>,
  <span class="hljs-string">&quot;scripts&quot;</span>: &#123;
    <span class="hljs-string">&quot;test&quot;</span>: <span class="hljs-string">&quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span>
  &#125;,
  <span class="hljs-string">&quot;author&quot;</span>: <span class="hljs-string">&quot;xiaochen&quot;</span>,
  <span class="hljs-string">&quot;license&quot;</span>: <span class="hljs-string">&quot;ISC&quot;</span>
&#125;


Is <span class="hljs-built_in">this</span> OK? (yes) yes</code></pre></div>

<p>对于目前来讲，最有用的是<code>dependencies</code>选项，可以用来帮助我们保存第三方包的依赖信息。</p>
<p>如果<code>node_modules</code>删除了也不用担心，只需要在控制面板中<code>npm install</code>就会自动把<code>package.json</code>中的<code>dependencies</code>中所有的依赖项全部都下载回来。</p>
<ul>
<li>建议每个项目的根目录下都有一个<code>package.json</code>文件</li>
<li>建议执行<code>npm install 包名</code>的时候都加上<code>--save</code>选项，目的是用来保存依赖信息</li>
</ul>
<h2 id="package-json和package-lock-json"><a href="#package-json和package-lock-json" class="headerlink" title="package.json和package-lock.json"></a>package.json和package-lock.json</h2><p>npm 5以前是不会有<code>package-lock.json</code>这个文件</p>
<p>npm5以后才加入这个文件</p>
<p>当你安装包的时候，npm都会生成或者更新<code>package-lock.json</code>这个文件</p>
<ul>
<li>npm5以后的版本安装都不要加<code>--save</code>参数，它会自动保存依赖信息</li>
<li>当你安装包的时候，会自动创建或者更新<code>package-lock.json</code>文件</li>
<li><code>package-lock.json</code>这个文件会包含<code>node_modules</code>中所有包的信息（版本，下载地址。。。）<ul>
<li>这样的话重新<code>npm install</code>的时候速度就可以提升</li>
</ul>
</li>
<li>从文件来看，有一个<code>lock</code>称之为锁<ul>
<li>这个<code>lock</code>使用来锁版本的</li>
<li>如果项目依赖了<code>1.1.1</code>版本</li>
<li>如果你重新install其实会下载最细版本，而不是<code>1.1.1</code></li>
<li><code>package-lock.json</code>的另外一个作用就是锁定版本号，防止自动升级</li>
</ul>
</li>
</ul>
<h2 id="path路径操作模块"><a href="#path路径操作模块" class="headerlink" title="path路径操作模块"></a>path路径操作模块</h2><blockquote>
<p>参考文档：<a target="_blank" rel="noopener" href="https://nodejs.org/docs/latest-v13.x/api/path.html">https://nodejs.org/docs/latest-v13.x/api/path.html</a></p>
</blockquote>
<ul>
<li>path.basename：获取路径的文件名，默认包含扩展名</li>
<li>path.dirname：获取路径中的目录部分</li>
<li>path.extname：获取一个路径中的扩展名部分</li>
<li>path.parse：把路径转换为对象<ul>
<li>root：根路径</li>
<li>dir：目录</li>
<li>base：包含后缀名的文件名</li>
<li>ext：后缀名</li>
<li>name：不包含后缀名的文件名</li>
</ul>
</li>
<li>path.join：拼接路径</li>
<li>path.isAbsolute：判断一个路径是否为绝对路径<img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200315150610001.png" srcset="/img/loading.gif" alt="image-20200315150610001"></li>
</ul>
<h1 id="Node中的其它成员-dirname-filename"><a href="#Node中的其它成员-dirname-filename" class="headerlink" title="Node中的其它成员(__dirname,__filename)"></a>Node中的其它成员(__dirname,__filename)</h1><p>在每个模块中，除了<code>require</code>,<code>exports</code>等模块相关的API之外，还有两个特殊的成员：</p>
<ul>
<li><p><code>__dirname</code>，是一个成员，可以用来<strong>动态</strong>获取当前文件模块所属目录的绝对路径</p>
</li>
<li><p><code>__filename</code>，可以用来<strong>动态</strong>获取当前文件的绝对路径（包含文件名）</p>
</li>
<li><p><code>__dirname</code>和<code>filename</code>是不受执行node命令所属路径影响的</p>
<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200315151551873.png" srcset="/img/loading.gif" alt="image-20200315151551873"></p>
</li>
</ul>
<p>在文件操作中，使用相对路径是不可靠的，因为node中文件操作的路径被设计为相对于执行node命令所处的路径。</p>
<p>所以为了解决这个问题，只需要把相对路径变为绝对路径（绝对路径不受任何影响）就可以了。</p>
<p>就可以使用<code>__dirname</code>或者<code>__filename</code>来帮助我们解决这个问题</p>
<p>在拼接路径的过程中，为了避免手动拼接带来的一些低级错误，推荐使用<code>path.join()</code>来辅助拼接</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);
<span class="hljs-keyword">var</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;path&#x27;</span>);

<span class="hljs-comment">// console.log(__dirname + &#x27;a.txt&#x27;);</span>
<span class="hljs-comment">// path.join方法会将文件操作中的相对路径都统一的转为动态的绝对路径</span>
fs.readFile(path.join(__dirname + <span class="hljs-string">&#x27;/a.txt&#x27;</span>),<span class="hljs-string">&#x27;utf8&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
	<span class="hljs-keyword">if</span>(err)&#123;
		<span class="hljs-keyword">throw</span> err
	&#125;
	<span class="hljs-built_in">console</span>.log(data);
&#125;);</code></pre></div>

<blockquote>
<p>补充：模块中的路径标识和这里的路径没关系，不受影响（就是相对于文件模块）</p>
</blockquote>
<blockquote>
<p><strong>注意：</strong></p>
<p><strong>模块中的路径标识和文件操作中的相对路径标识不一致</strong></p>
<p><strong>模块中的路径标识就是相对于当前文件模块，不受node命令所处路径影响</strong></p>
</blockquote>
<h1 id="Express（快速的）"><a href="#Express（快速的）" class="headerlink" title="Express（快速的）"></a>Express（快速的）</h1><p>作者：Tj</p>
<p>原生的http在某些方面表现不足以应对我们的开发需求，所以就需要使用框架来加快我们的开发效率，框架的目的就是提高效率，让我们的代码高度统一。</p>
<p>在node中有很多web开发框架。主要学习express</p>
<ul>
<li><p><code>http://expressjs.com/</code>,其中主要封装的是http。</p>
</li>
<li><div class="hljs"><pre><code class="javascript">// 1 安装
// 2 引包
var express = require(&#39;express&#39;);
// 3 创建服务器应用程序
//      也就是原来的http.createServer();
var app = express();

// 公开指定目录
// 只要通过这样做了，就可以通过/public/xx的方式来访问public目录中的所有资源
// 在Express中开放资源就是一个API的事
app.use(&#39;/public/&#39;,express.static(&#39;/public/&#39;));

//模板引擎在Express中开放模板也是一个API的事

// 当服务器收到get请求 / 的时候，执行回调处理函数
app.get(&#39;/&#39;,function(req,res)&#123;
    res.send(&#39;hello express&#39;);
&#125;)

// 相当于server.listen
app.listen(3000,function()&#123;
    console.log(&#39;app is runing at port 3000&#39;);
&#125;)
<pre><code class="hljs">

### 学习Express

#### 起步

##### 安装：![image-20200310123723079](C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200310123723079.png)

```javascript
cnpm install express</code></pre></div>
</code></pre>
</li>
</ul>
<h5 id="hello-world"><a href="#hello-world" class="headerlink" title="hello world:"></a>hello world:<img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200310124850557.png" srcset="/img/loading.gif" alt="image-20200310124850557"></h5><div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 引入express</span>
<span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>);

<span class="hljs-comment">// 1. 创建app</span>
<span class="hljs-keyword">var</span> app = express();

<span class="hljs-comment">//  2. </span>
app.get(<span class="hljs-string">&#x27;/&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    <span class="hljs-comment">// 1</span>
    <span class="hljs-comment">// res.write(&#x27;Hello&#x27;);</span>
    <span class="hljs-comment">// res.write(&#x27;World&#x27;);</span>
    <span class="hljs-comment">// res.end()</span>

    <span class="hljs-comment">// 2</span>
    <span class="hljs-comment">// res.end(&#x27;hello world&#x27;);</span>

    <span class="hljs-comment">// 3</span>
    res.send(<span class="hljs-string">&#x27;hello world&#x27;</span>);
&#125;)

app.listen(<span class="hljs-number">3000</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;express app is runing...&#x27;</span>);
&#125;)</code></pre></div>

<h5 id="基本路由"><a href="#基本路由" class="headerlink" title="基本路由"></a>基本路由</h5><p>路由：</p>
<ul>
<li><p>请求方法</p>
</li>
<li><p>请求路径</p>
</li>
<li><p>请求处理函数</p>
</li>
</ul>
<p>get:</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">//当你以get方法请求/的时候，执行对应的处理函数</span>
app.get(<span class="hljs-string">&#x27;/&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    res.send(<span class="hljs-string">&#x27;hello world&#x27;</span>);
&#125;)</code></pre></div>

<p>post:</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">//当你以post方法请求/的时候，执行对应的处理函数</span>
app.post(<span class="hljs-string">&#x27;/&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    res.send(<span class="hljs-string">&#x27;hello world&#x27;</span>);
&#125;)</code></pre></div>

<h5 id="Express静态服务API"><a href="#Express静态服务API" class="headerlink" title="Express静态服务API"></a>Express静态服务API</h5><div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// app.use不仅仅是用来处理静态资源的，还可以做很多工作(body-parser的配置)</span>
app.use(express.static(<span class="hljs-string">&#x27;public&#x27;</span>));

app.use(express.static(<span class="hljs-string">&#x27;files&#x27;</span>));

app.use(<span class="hljs-string">&#x27;/stataic&#x27;</span>,express.static(<span class="hljs-string">&#x27;public&#x27;</span>));</code></pre></div>

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 引入express</span>
<span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>);

<span class="hljs-comment">// 创建app</span>
<span class="hljs-keyword">var</span> app = express();

<span class="hljs-comment">// 开放静态资源</span>
<span class="hljs-comment">// 1.当以/public/开头的时候，去./public/目录中找对应资源</span>
<span class="hljs-comment">// 访问：http://127.0.0.1:3000/public/login.html</span>
app.use(<span class="hljs-string">&#x27;/public/&#x27;</span>,express.static(<span class="hljs-string">&#x27;./public/&#x27;</span>)); 

<span class="hljs-comment">// 2.当省略第一个参数的时候，可以通过省略/public的方式来访问</span>
<span class="hljs-comment">// 访问：http://127.0.0.1:3000/login.html</span>
<span class="hljs-comment">// app.use(express.static(&#x27;./public/&#x27;));   </span>

<span class="hljs-comment">// 3.访问：http://127.0.0.1:3000/a/login.html</span>
<span class="hljs-comment">// a相当于public的别名</span>
<span class="hljs-comment">// app.use(&#x27;/a/&#x27;,express.static(&#x27;./public/&#x27;)); </span>

<span class="hljs-comment">//  </span>
app.get(<span class="hljs-string">&#x27;/&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    res.end(<span class="hljs-string">&#x27;hello world&#x27;</span>);
&#125;);

app.listen(<span class="hljs-number">3000</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;express app is runing...&#x27;</span>);
&#125;);</code></pre></div>

<h5 id="在Express中配置使用art-templete模板引擎"><a href="#在Express中配置使用art-templete模板引擎" class="headerlink" title="在Express中配置使用art-templete模板引擎"></a>在Express中配置使用<code>art-templete</code>模板引擎</h5><ul>
<li><a target="_blank" rel="noopener" href="https://aui.github.io/art-template/">art-template官方文档</a></li>
<li>在node中，有很多第三方模板引擎都可以使用，不是只有<code>art-template</code><ul>
<li>还有ejs，jade（pug），handlebars，nunjucks</li>
</ul>
</li>
</ul>
<p>安装：</p>
<div class="hljs"><pre><code class="hljs shell">npm install --save art-template
npm install --save express-art-template

//两个一起安装
npm i --save art-template express-art-template</code></pre></div>

<p>配置：</p>
<div class="hljs"><pre><code class="hljs javascript">app.engine(<span class="hljs-string">&#x27;html&#x27;</span>, <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express-art-template&#x27;</span>));</code></pre></div>

<p>使用：</p>
<div class="hljs"><pre><code class="hljs javascript">app.get(<span class="hljs-string">&#x27;/&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    <span class="hljs-comment">// express默认会去views目录找index.html</span>
    res.render(<span class="hljs-string">&#x27;index.html&#x27;</span>,&#123;
           title:<span class="hljs-string">&#x27;hello world&#x27;</span>     
    &#125;);
&#125;)</code></pre></div>

<p>如果希望修改默认的<code>views</code>视图渲染存储目录，可以：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 第一个参数views千万不要写错</span>
app.set(<span class="hljs-string">&#x27;views&#x27;</span>,目录路径);</code></pre></div>

<h5 id="在Express中获取表单请求数据"><a href="#在Express中获取表单请求数据" class="headerlink" title="在Express中获取表单请求数据"></a>在Express中获取表单请求数据</h5><h6 id="获取get请求数据："><a href="#获取get请求数据：" class="headerlink" title="获取get请求数据："></a>获取get请求数据：</h6><p>Express内置了一个api，可以直接通过<code>req.query</code>来获取数据</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 通过requery方法获取用户输入的数据</span>
<span class="hljs-comment">// req.query只能拿到get请求的数据</span>
 <span class="hljs-keyword">var</span> comment = req.query;</code></pre></div>

<h6 id="获取post请求数据："><a href="#获取post请求数据：" class="headerlink" title="获取post请求数据："></a>获取post请求数据：</h6><p>在Express中没有内置获取表单post请求体的api，这里我们需要使用一个第三方包<code>body-parser</code>来获取数据。</p>
<p>安装：</p>
<div class="hljs"><pre><code class="hljs javascript">npm install --save body-parser;</code></pre></div>

<p>配置：</p>
<p>// 配置解析表单 POST 请求体插件（注意：一定要在 app.use(router) 之前 ）</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)
<span class="hljs-comment">// 引包</span>
<span class="hljs-keyword">var</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;body-parser&#x27;</span>)

<span class="hljs-keyword">var</span> app = express()

<span class="hljs-comment">// 配置body-parser</span>
<span class="hljs-comment">// 只要加入这个配置，则在req请求对象上会多出来一个属性：body</span>
<span class="hljs-comment">// 也就是说可以直接通过req.body来获取表单post请求数据</span>
<span class="hljs-comment">// parse application/x-www-form-urlencoded</span>
app.use(bodyParser.urlencoded(&#123; <span class="hljs-attr">extended</span>: <span class="hljs-literal">false</span> &#125;))

<span class="hljs-comment">// parse application/json</span>
app.use(bodyParser.json())</code></pre></div>

<p>使用：</p>
<div class="hljs"><pre><code class="hljs javascript">app.use(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, res</span>) </span>&#123;
  res.setHeader(<span class="hljs-string">&#x27;Content-Type&#x27;</span>, <span class="hljs-string">&#x27;text/plain&#x27;</span>)
  res.write(<span class="hljs-string">&#x27;you posted:\n&#x27;</span>)
  <span class="hljs-comment">// 可以通过req.body来获取表单请求数据</span>
  res.end(<span class="hljs-built_in">JSON</span>.stringify(req.body, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>))
&#125;)</code></pre></div>

<h3 id="在Express中配置使用express-session插件操作"><a href="#在Express中配置使用express-session插件操作" class="headerlink" title="在Express中配置使用express-session插件操作"></a>在Express中配置使用<code>express-session</code>插件操作</h3><blockquote>
<p>参考文档：<a target="_blank" rel="noopener" href="https://github.com/expressjs/session">https://github.com/expressjs/session</a></p>
</blockquote>
<p>安装：</p>
<div class="hljs"><pre><code class="hljs javascript">npm install express-session</code></pre></div>

<p>配置：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">//该插件会为req请求对象添加一个成员:req.session默认是一个对象</span>
<span class="hljs-comment">//这是最简单的配置方式</span>
<span class="hljs-comment">//Session是基于Cookie实现的</span>
app.use(session(&#123;
  <span class="hljs-comment">//配置加密字符串，他会在原有的基础上和字符串拼接起来去加密</span>
  <span class="hljs-comment">//目的是为了增加安全性，防止客户端恶意伪造</span>
  secret: <span class="hljs-string">&#x27;keyboard cat&#x27;</span>,
  resave: <span class="hljs-literal">false</span>,
  saveUninitialized: <span class="hljs-literal">true</span>,<span class="hljs-comment">//无论是否适用Session，都默认直接分配一把钥匙</span>
  cookie: &#123; <span class="hljs-attr">secure</span>: <span class="hljs-literal">true</span> &#125;
&#125;))</code></pre></div>

<p>使用：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 读</span>
<span class="hljs-comment">//添加Session数据</span>
<span class="hljs-comment">//session就是一个对象</span>
req.session.foo = <span class="hljs-string">&#x27;bar&#x27;</span>;

<span class="hljs-comment">//写</span>
<span class="hljs-comment">//获取session数据</span>
req.session.foo

<span class="hljs-comment">//删</span>
req.session.foo = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">delete</span> req.session.foo</code></pre></div>

<p>提示：</p>
<p>默认Session数据时内存储数据，服务器一旦重启，真正的生产环境会把Session进行持久化存储。</p>
<h3 id="利用Express实现ADUS项目"><a href="#利用Express实现ADUS项目" class="headerlink" title="利用Express实现ADUS项目"></a>利用Express实现ADUS项目</h3><h4 id="模块化思想"><a href="#模块化思想" class="headerlink" title="模块化思想"></a>模块化思想</h4><p>模块如何划分:</p>
<ul>
<li>模块职责要单一</li>
</ul>
<p>javascript模块化：</p>
<ul>
<li>Node 中的 CommonJS</li>
<li>浏览器中的：<ul>
<li>AMD    require.js</li>
<li>CMD     sea.js</li>
</ul>
</li>
<li>es6中增加了官方支持</li>
</ul>
<h4 id="起步-1"><a href="#起步-1" class="headerlink" title="起步"></a>起步</h4><ul>
<li>初始化</li>
<li>模板处理</li>
</ul>
<h4 id="路由设计"><a href="#路由设计" class="headerlink" title="路由设计"></a>路由设计</h4><table>
<thead>
<tr>
<th>请求方法</th>
<th align="left">请求路径</th>
<th align="left">get参数</th>
<th>post参数</th>
<th align="left">备注</th>
</tr>
</thead>
<tbody><tr>
<td>GET</td>
<td align="left">/students</td>
<td align="left"></td>
<td></td>
<td align="left">渲染首页</td>
</tr>
<tr>
<td>GET</td>
<td align="left">/students/new</td>
<td align="left"></td>
<td></td>
<td align="left">渲染添加学生页面</td>
</tr>
<tr>
<td>POST</td>
<td align="left">/students/new</td>
<td align="left"></td>
<td>name,age,gender,hobbies</td>
<td align="left">处理添加学生请求</td>
</tr>
<tr>
<td>GET</td>
<td align="left">/students/edit</td>
<td align="left">id</td>
<td></td>
<td align="left">渲染编辑页面</td>
</tr>
<tr>
<td>POST</td>
<td align="left">/students/edit</td>
<td align="left"></td>
<td>id,name,age,gender,hobbies</td>
<td align="left">处理编辑请求</td>
</tr>
<tr>
<td>GET</td>
<td align="left">/students/delete</td>
<td align="left">id</td>
<td></td>
<td align="left">处理删除请求</td>
</tr>
</tbody></table>
<h4 id="提取路由模块"><a href="#提取路由模块" class="headerlink" title="提取路由模块"></a>提取路由模块</h4><p>router.js:</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * router.js路由模块</span>
<span class="hljs-comment"> * 职责：</span>
<span class="hljs-comment"> *      处理路由</span>
<span class="hljs-comment"> *      根据不同的请求方法+请求路径设置具体的请求函数</span>
<span class="hljs-comment"> * 模块职责要单一，我们划分模块的目的就是增强代码的可维护性，提升开发效率</span>
<span class="hljs-comment"> */</span>
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);

<span class="hljs-comment">// Express专门提供了一种更好的方式</span>
<span class="hljs-comment">// 专门用来提供路由的</span>
<span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>);
<span class="hljs-comment">// 1 创建一个路由容器</span>
<span class="hljs-keyword">var</span> router = express.Router();
<span class="hljs-comment">// 2 把路由都挂载到路由容器中</span>

router.get(<span class="hljs-string">&#x27;/students&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) </span>&#123;
    <span class="hljs-comment">// res.send(&#x27;hello world&#x27;);</span>
    <span class="hljs-comment">// readFile的第二个参数是可选的，传入utf8就是告诉他把读取到的文件直接按照utf8编码，直接转成我们认识的字符</span>
    <span class="hljs-comment">// 除了这样来转换，也可以通过data.toString（）来转换</span>
    fs.readFile(<span class="hljs-string">&#x27;./db.json&#x27;</span>, <span class="hljs-string">&#x27;utf8&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, data</span>) </span>&#123;
        <span class="hljs-keyword">if</span> (err) &#123;
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">&#x27;Server error.&#x27;</span>)
        &#125;
        <span class="hljs-comment">// 读取到的文件数据是string类型的数据</span>
        <span class="hljs-comment">// console.log(data);</span>
        <span class="hljs-comment">// 从文件中读取到的数据一定是字符串，所以一定要手动转换成对象</span>
        <span class="hljs-keyword">var</span> students = <span class="hljs-built_in">JSON</span>.parse(data).students;
        res.render(<span class="hljs-string">&#x27;index.html&#x27;</span>, &#123;
            <span class="hljs-comment">// 读取文件数据</span>
            students:students
        &#125;)
    &#125;)
&#125;);

router.get(<span class="hljs-string">&#x27;/students/new&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    res.render(<span class="hljs-string">&#x27;new.html&#x27;</span>)
&#125;);

router.get(<span class="hljs-string">&#x27;/students/edit&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    
&#125;);

router.post(<span class="hljs-string">&#x27;/students/edit&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    
&#125;);

router.get(<span class="hljs-string">&#x27;/students/delete&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    
&#125;);

<span class="hljs-comment">// 3 把router导出</span>
<span class="hljs-built_in">module</span>.exports = router;
</code></pre></div>

<p>app.js:</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> router = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./router&#x27;</span>);

<span class="hljs-comment">// router(app);</span>
<span class="hljs-comment">// 把路由容器挂载到app服务中</span>
<span class="hljs-comment">// 挂载路由</span>
app.use(router);</code></pre></div>



<h4 id="设计操作数据的API文件模块"><a href="#设计操作数据的API文件模块" class="headerlink" title="设计操作数据的API文件模块"></a>设计操作数据的API文件模块</h4><p>es6中的find和findIndex：</p>
<p>find接受一个方法作为参数，方法内部返回一个条件</p>
<p>find会便利所有的元素，执行你给定的带有条件返回值的函数</p>
<p>符合该条件的元素会作为find方法的返回值</p>
<p>如果遍历结束还没有符合该条件的元素，则返回undefined<img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200313103810731.png" srcset="/img/loading.gif" alt="image-20200313103810731"></p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * student.js</span>
<span class="hljs-comment"> * 数据操作文件模块</span>
<span class="hljs-comment"> * 职责：操作文件中的数据，只处理数据，不关心业务</span>
<span class="hljs-comment"> */</span>
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);
 <span class="hljs-comment">/**</span>
<span class="hljs-comment">  * 获取所有学生列表</span>
<span class="hljs-comment">  * return []</span>
<span class="hljs-comment">  */</span>
<span class="hljs-built_in">exports</span>.find = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
    
&#125;


 <span class="hljs-comment">/**</span>
<span class="hljs-comment">  * 获取添加保存学生</span>
<span class="hljs-comment">  */</span>
<span class="hljs-built_in">exports</span>.save = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        
&#125;

<span class="hljs-comment">/**</span>
<span class="hljs-comment"> * 更新学生</span>
<span class="hljs-comment"> */</span>
<span class="hljs-built_in">exports</span>.update = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        
&#125;

 <span class="hljs-comment">/**</span>
<span class="hljs-comment"> * 删除学生</span>
<span class="hljs-comment"> */</span>
<span class="hljs-built_in">exports</span>.delete = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        
&#125;</code></pre></div>

<h4 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h4><ul>
<li><p>处理模板</p>
</li>
<li><p>配置静态开放资源</p>
</li>
<li><p>配置模板引擎</p>
</li>
<li><p>简单的路由，/studens渲染静态页出来</p>
</li>
<li><p>路由设计</p>
</li>
<li><p>提取路由模块</p>
</li>
<li><p>由于接下来的一系列业务操作都需要处理文件数据，所以我们需要封装Student.js’</p>
</li>
<li><p>先写好student.js文件结构</p>
<ul>
<li>查询所有学生列别哦的API</li>
<li>findById</li>
<li>save</li>
<li>updateById</li>
<li>deleteById</li>
</ul>
</li>
<li><p>实现具体功能</p>
<ul>
<li>通过路由收到请求</li>
<li>接受请求中的参数（get，post）<ul>
<li>req.query</li>
<li>req.body</li>
</ul>
</li>
<li>调用数据操作API处理数据</li>
<li>根据操作结果给客户端发送请求</li>
</ul>
</li>
<li><p>业务功能顺序</p>
<ul>
<li>列表</li>
<li>添加</li>
<li>编辑</li>
<li>删除</li>
</ul>
</li>
</ul>
<h4 id="子模板和模板的继承（模板引擎高级语法）【include，extend，block】"><a href="#子模板和模板的继承（模板引擎高级语法）【include，extend，block】" class="headerlink" title="子模板和模板的继承（模板引擎高级语法）【include，extend，block】"></a>子模板和模板的继承（模板引擎高级语法）【include，extend，block】</h4><p>注意:</p>
<p>模板页：</p>
<div class="hljs"><pre><code class="hljs javascript">&lt;!DOCTYPE html&gt;
&lt;html lang=<span class="hljs-string">&quot;zh&quot;</span>&gt;
&lt;head&gt;
	&lt;meta charset=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;
	&lt;meta name=<span class="hljs-string">&quot;viewport&quot;</span> content=<span class="hljs-string">&quot;width=device-width, initial-scale=1.0&quot;</span>&gt;
	&lt;meta http-equiv=<span class="hljs-string">&quot;X-UA-Compatible&quot;</span> content=<span class="hljs-string">&quot;ie=edge&quot;</span>&gt;
	&lt;title&gt;模板页&lt;/title&gt;
	&lt;link rel=<span class="hljs-string">&quot;stylesheet&quot;</span> href=<span class="hljs-string">&quot;/node_modules/bootstrap/dist/css/bootstrap.css&quot;</span>/&gt;
	&#123;&#123; block <span class="hljs-string">&#x27;head&#x27;</span> &#125;&#125;&#123;&#123; /block &#125;&#125;
&lt;/head&gt;
&lt;body&gt;
	&lt;!-- 通过include导入公共部分 --&gt;
	&#123;&#123;include <span class="hljs-string">&#x27;./header.html&#x27;</span>&#125;&#125;
	
	&lt;!-- 留一个位置 让别的内容去填充 --&gt;
	&#123;&#123; block  <span class="hljs-string">&#x27;content&#x27;</span> &#125;&#125;
		&lt;h1&gt;默认内容&lt;/h1&gt;
	&#123;&#123; /block &#125;&#125;
	
	&lt;!-- 通过include导入公共部分 --&gt;
	&#123;&#123;include <span class="hljs-string">&#x27;./footer.html&#x27;</span>&#125;&#125;
	
	&lt;!-- 公共样式 --&gt;
	&lt;script src=<span class="hljs-string">&quot;/node_modules/jquery/dist/jquery.js&quot;</span> &gt;&lt;/script&gt;
	&lt;script src=<span class="hljs-string">&quot;/node_modules/bootstrap/dist/js/bootstrap.js&quot;</span> &gt;&lt;/script&gt;
	&#123;&#123; block <span class="hljs-string">&#x27;script&#x27;</span> &#125;&#125;&#123;&#123; /block &#125;&#125;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>

<p>模板的继承：</p>
<p>​    header页面：</p>
<div class="hljs"><pre><code class="hljs javascript">&lt;div id=<span class="hljs-string">&quot;&quot;</span>&gt;
	&lt;h1&gt;公共的头部&lt;/h1&gt;
&lt;/div&gt;</code></pre></div>

<p>​    footer页面：</p>
<div class="hljs"><pre><code class="hljs javascript">&lt;div id=<span class="hljs-string">&quot;&quot;</span>&gt;
	&lt;h1&gt;公共的底部&lt;/h1&gt;
&lt;/div&gt;</code></pre></div>

<p>模板页的使用：</p>
<div class="hljs"><pre><code class="hljs javascript">&lt;!-- 继承(extend:延伸，扩展)模板也layout.html --&gt;
&lt;!-- 把layout.html页面的内容都拿进来作为index.html页面的内容 --&gt;
&#123;&#123;extend <span class="hljs-string">&#x27;./layout.html&#x27;</span>&#125;&#125;

&lt;!-- 向模板页面填充新的数据 --&gt;
&lt;!-- 填充后就会替换掉layout页面content中的数据 --&gt;
&lt;!-- style样式方面的内容 --&gt;
&#123;&#123; block <span class="hljs-string">&#x27;head&#x27;</span> &#125;&#125;
	&lt;style type=<span class="hljs-string">&quot;text/css&quot;</span>&gt;
		body&#123;
			background-color: skyblue;
		&#125;
	&lt;/style&gt;
&#123;&#123; /block &#125;&#125;
&#123;&#123; block <span class="hljs-string">&#x27;content&#x27;</span> &#125;&#125;
	&lt;div id=<span class="hljs-string">&quot;&quot;</span>&gt;
		&lt;h1&gt;Index页面的内容&lt;/h1&gt;
	&lt;/div&gt;
&#123;&#123; /block &#125;&#125;
&lt;!-- js部分的内容 --&gt;
&#123;&#123; block <span class="hljs-string">&#x27;script&#x27;</span> &#125;&#125;
	&lt;script type=<span class="hljs-string">&quot;text/javascript&quot;</span>&gt;
		
	&lt;/script&gt;
&#123;&#123; /block &#125;&#125;</code></pre></div>

<p>最终的显示效果：</p>
<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200316134759517.png" srcset="/img/loading.gif" alt="image-20200316134759517"></p>
<h1 id="MongoDB"><a href="#MongoDB" class="headerlink" title="MongoDB"></a>MongoDB</h1><h2 id="关系型和非关系型数据库"><a href="#关系型和非关系型数据库" class="headerlink" title="关系型和非关系型数据库"></a>关系型和非关系型数据库</h2><h3 id="关系型数据库（表就是关系，或者说表与表之间存在关系）。"><a href="#关系型数据库（表就是关系，或者说表与表之间存在关系）。" class="headerlink" title="关系型数据库（表就是关系，或者说表与表之间存在关系）。"></a>关系型数据库（表就是关系，或者说表与表之间存在关系）。</h3><ul>
<li>所有的关系型数据库都需要通过<code>sql</code>语言来操作</li>
<li>所有的关系型数据库在操作之前都需要设计表结构</li>
<li>而且数据表还支持约束<ul>
<li>唯一的</li>
<li>主键</li>
<li>默认值</li>
<li>非空</li>
</ul>
</li>
</ul>
<h3 id="非关系型数据库"><a href="#非关系型数据库" class="headerlink" title="非关系型数据库"></a>非关系型数据库</h3><ul>
<li>非关系型数据库非常的灵活</li>
<li>有的关系型数据库就是key-value对儿</li>
<li>但MongDB是长得最像关系型数据库的非关系型数据库<ul>
<li>数据库 -》 数据库</li>
<li>数据表 -》 集合（数组）</li>
<li>表记录 -》文档对象</li>
</ul>
</li>
</ul>
<p>一个数据库中可以有多个数据库，一个数据库中可以有多个集合（数组），一个集合中可以有多个文档（表记录）</p>
<div class="hljs"><pre><code class="hljs javascript">&#123;
    qq:&#123;
       user:[
           &#123;&#125;,&#123;&#125;,&#123;&#125;...
       ]
    &#125;
&#125;</code></pre></div>



<ul>
<li>也就是说你可以任意的往里面存数据，没有结构性这么一说</li>
</ul>
<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><ul>
<li><p>下载</p>
<ul>
<li>下载地址：<a target="_blank" rel="noopener" href="https://www.mongodb.com/download-center/community">https://www.mongodb.com/download-center/community</a></li>
</ul>
</li>
<li><p>安装</p>
<div class="hljs"><pre><code class="hljs javascript">npm i mongoose</code></pre></div>
</li>
<li><p>配置环境变量</p>
</li>
<li><p>最后输入<code>mongod --version</code>测试是否安装成功</p>
</li>
</ul>
<h2 id="启动和关闭数据库"><a href="#启动和关闭数据库" class="headerlink" title="启动和关闭数据库"></a>启动和关闭数据库</h2><p>启动：</p>
<div class="hljs"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash"> mongodb 默认使用执行mongod 命令所处盼复根目录下的/data/db作为自己的数据存储目录</span>
<span class="hljs-meta">#</span><span class="bash"> 所以在第一次执行该命令之前先自己手动新建一个 /data/db</span>
mongod</code></pre></div>

<p>如果想要修改默认的数据存储目录，可以：</p>
<div class="hljs"><pre><code class="hljs javascript">mongod --dbpath = 数据存储目录路径</code></pre></div>

<p>停止：</p>
<div class="hljs"><pre><code class="hljs javascript">在开启服务的控制台，直接Ctrl+C;
或者直接关闭开启服务的控制台。</code></pre></div>

<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314101047100.png" srcset="/img/loading.gif" alt="image-20200314101047100"></p>
<h2 id="连接数据库"><a href="#连接数据库" class="headerlink" title="连接数据库"></a>连接数据库</h2><p>连接：</p>
<div class="hljs"><pre><code class="hljs javascript"># 该命令默认连接本机的 MongoDB 服务
mongo</code></pre></div>

<p>退出：</p>
<div class="hljs"><pre><code class="hljs javascript"># 在连接状态输入 exit 退出连接
exit</code></pre></div>



<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314100821112.png" srcset="/img/loading.gif" alt="image-20200314100821112"></p>
<h2 id="基本命令"><a href="#基本命令" class="headerlink" title="基本命令"></a>基本命令</h2><ul>
<li><code>show dbs</code><ul>
<li>查看数据库列表(数据库中的所有数据库)</li>
</ul>
</li>
<li><code>db</code><ul>
<li>查看当前连接的数据库</li>
</ul>
</li>
<li><code>use 数据库名称</code><ul>
<li>切换到指定的数据库，（如果没有会新建）</li>
</ul>
</li>
<li><code>show collections</code><ul>
<li>查看当前目录下的所有数据表</li>
</ul>
</li>
<li><code>db.表名.find()</code><ul>
<li>查看表中的详细信息</li>
</ul>
</li>
</ul>
<h2 id="在Node中如何操作MongoDB数据库"><a href="#在Node中如何操作MongoDB数据库" class="headerlink" title="在Node中如何操作MongoDB数据库"></a>在Node中如何操作MongoDB数据库</h2><h3 id="使用官方的MongoDB包来操作"><a href="#使用官方的MongoDB包来操作" class="headerlink" title="使用官方的MongoDB包来操作"></a>使用官方的<code>MongoDB</code>包来操作</h3><blockquote>
<p>​    <a target="_blank" rel="noopener" href="http://mongodb.github.io/node-mongodb-native/">http://mongodb.github.io/node-mongodb-native/</a></p>
</blockquote>
<h3 id="使用第三方包mongoose来操作MongoDB数据库"><a href="#使用第三方包mongoose来操作MongoDB数据库" class="headerlink" title="使用第三方包mongoose来操作MongoDB数据库"></a>使用第三方包<code>mongoose</code>来操作MongoDB数据库</h3><p>​    第三方包：<code>mongoose</code>基于MongoDB官方的<code>mongodb</code>包再一次做了封装，名字叫<code>mongoose</code>，是WordPress项目团队开发的。</p>
<blockquote>
<p>​    <a target="_blank" rel="noopener" href="https://mongoosejs.com/">https://mongoosejs.com/</a></p>
</blockquote>
<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314105632745.png" srcset="/img/loading.gif" alt="image-20200314105632745"></p>
<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314105717993.png" srcset="/img/loading.gif" alt="image-20200314105717993"></p>
<h2 id="学习指南（步骤）"><a href="#学习指南（步骤）" class="headerlink" title="学习指南（步骤）"></a>学习指南（步骤）</h2><p>官方学习文档：<a target="_blank" rel="noopener" href="https://mongoosejs.com/docs/index.html">https://mongoosejs.com/docs/index.html</a></p>
<h3 id="设计Scheme-发布Model-创建表"><a href="#设计Scheme-发布Model-创建表" class="headerlink" title="设计Scheme 发布Model (创建表)"></a>设计Scheme 发布Model (创建表)</h3><div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 1.引包</span>
<span class="hljs-comment">// 注意：按照后才能require使用</span>
<span class="hljs-keyword">var</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;mongoose&#x27;</span>);

<span class="hljs-comment">// 拿到schema图表</span>
<span class="hljs-keyword">var</span> Schema = mongoose.Schema;

<span class="hljs-comment">// 2.连接数据库</span>
<span class="hljs-comment">// 指定连接数据库后不需要存在，当你插入第一条数据库后会自动创建数据库</span>
mongoose.connect(<span class="hljs-string">&#x27;mongodb://localhost/test&#x27;</span>);

<span class="hljs-comment">// 3.设计集合结构（表结构）</span>
<span class="hljs-comment">// 用户表</span>
<span class="hljs-keyword">var</span> userSchema = <span class="hljs-keyword">new</span> Schema(&#123;
	username: &#123; <span class="hljs-comment">//姓名</span>
		type: <span class="hljs-built_in">String</span>,
		<span class="hljs-built_in">require</span>: <span class="hljs-literal">true</span> <span class="hljs-comment">//添加约束，保证数据的完整性，让数据按规矩统一</span>
	&#125;,
	password: &#123;
		type: <span class="hljs-built_in">String</span>,
		<span class="hljs-built_in">require</span>: <span class="hljs-literal">true</span>
	&#125;,
	email: &#123;
		type: <span class="hljs-built_in">String</span>
	&#125;
&#125;);

<span class="hljs-comment">// 4.将文档结构发布为模型</span>
<span class="hljs-comment">// mongoose.model方法就是用来将一个架构发布为 model</span>
<span class="hljs-comment">// 		第一个参数：传入一个大写名词单数字符串用来表示你的数据库的名称</span>
<span class="hljs-comment">// 					mongoose 会自动将大写名词的字符串生成 小写复数 的集合名称</span>
<span class="hljs-comment">// 					例如 这里会变成users集合名称</span>
<span class="hljs-comment">// 		第二个参数：架构</span>
<span class="hljs-comment">// 	返回值：模型构造函数</span>
<span class="hljs-keyword">var</span> User = mongoose.model(<span class="hljs-string">&#x27;User&#x27;</span>, userSchema);</code></pre></div>

<h3 id="添加数据（增）"><a href="#添加数据（增）" class="headerlink" title="添加数据（增）"></a>添加数据（增）</h3><div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 5.通过模型构造函数对User中的数据进行操作</span>
<span class="hljs-keyword">var</span> user = <span class="hljs-keyword">new</span> User(&#123;
	username: <span class="hljs-string">&#x27;admin&#x27;</span>,
	password: <span class="hljs-string">&#x27;123456&#x27;</span>,
	email: <span class="hljs-string">&#x27;xiaochen@qq.com&#x27;</span>
&#125;);

user.save(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, ret</span>) </span>&#123;
	<span class="hljs-keyword">if</span> (err) &#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;保存失败&#x27;</span>);
	&#125; <span class="hljs-keyword">else</span> &#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;保存成功&#x27;</span>);
		<span class="hljs-built_in">console</span>.log(ret);
	&#125;
&#125;);</code></pre></div>

<h3 id="删除（删）"><a href="#删除（删）" class="headerlink" title="删除（删）"></a>删除（删）</h3><p>根据条件删除所有：</p>
<div class="hljs"><pre><code class="hljs javascript">User.remove(&#123;
	username: <span class="hljs-string">&#x27;xiaoxiao&#x27;</span>
&#125;, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, ret</span>) </span>&#123;
	<span class="hljs-keyword">if</span> (err) &#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;删除失败&#x27;</span>);
	&#125; <span class="hljs-keyword">else</span> &#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;删除成功&#x27;</span>);
		<span class="hljs-built_in">console</span>.log(ret);
	&#125;
&#125;);</code></pre></div>

<p>根据条件删除一个：</p>
<div class="hljs"><pre><code class="hljs javascript">Model.findOneAndRemove(conditions,[options],[callback]);</code></pre></div>

<p>根据id删除一个：</p>
<div class="hljs"><pre><code class="hljs javascript">User.findByIdAndRemove(id,[options],[callback]);</code></pre></div>



<h3 id="更新（改）"><a href="#更新（改）" class="headerlink" title="更新（改）"></a>更新（改）</h3><p>更新所有：</p>
<div class="hljs"><pre><code class="hljs javascript">User.remove(conditions,doc,[options],[callback]);</code></pre></div>

<p>根据指定条件更新一个：</p>
<div class="hljs"><pre><code class="hljs javascript">User.FindOneAndUpdate([conditions],[update],[options],[callback]);</code></pre></div>

<p>根据id更新一个：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 更新	根据id来修改表数据</span>
User.findByIdAndUpdate(<span class="hljs-string">&#x27;5e6c5264fada77438c45dfcd&#x27;</span>, &#123;
	username: <span class="hljs-string">&#x27;junjun&#x27;</span>
&#125;, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, ret</span>) </span>&#123;
	<span class="hljs-keyword">if</span> (err) &#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;更新失败&#x27;</span>);
	&#125; <span class="hljs-keyword">else</span> &#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;更新成功&#x27;</span>);
	&#125;
&#125;);</code></pre></div>



<h3 id="查询（查）"><a href="#查询（查）" class="headerlink" title="查询（查）"></a>查询（查）</h3><p>查询所有：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 查询所有</span>
User.find(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,ret</span>)</span>&#123;
	<span class="hljs-keyword">if</span>(err)&#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;查询失败&#x27;</span>);
	&#125;<span class="hljs-keyword">else</span>&#123;
		<span class="hljs-built_in">console</span>.log(ret);
	&#125;
&#125;);</code></pre></div>

<p>条件查询所有：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 根据条件查询</span>
User.find(&#123; <span class="hljs-attr">username</span>:<span class="hljs-string">&#x27;xiaoxiao&#x27;</span> &#125;,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,ret</span>)</span>&#123;
	<span class="hljs-keyword">if</span>(err)&#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;查询失败&#x27;</span>);
	&#125;<span class="hljs-keyword">else</span>&#123;
		<span class="hljs-built_in">console</span>.log(ret);
	&#125;
&#125;);</code></pre></div>

<p>条件查询单个：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 按照条件查询单个，查询出来的数据是一个对象（&#123;&#125;）</span>
<span class="hljs-comment">// 没有条件查询使用findOne方法，查询的是表中的第一条数据</span>
User.findOne(&#123;
	username: <span class="hljs-string">&#x27;xiaoxiao&#x27;</span>
&#125;, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, ret</span>) </span>&#123;
	<span class="hljs-keyword">if</span> (err) &#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;查询失败&#x27;</span>);
	&#125; <span class="hljs-keyword">else</span> &#123;
		<span class="hljs-built_in">console</span>.log(ret);
	&#125;
&#125;);</code></pre></div>

<h1 id="使用Node操作MySQL数据库"><a href="#使用Node操作MySQL数据库" class="headerlink" title="使用Node操作MySQL数据库"></a>使用Node操作MySQL数据库</h1><p>文档：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/mysql">https://www.npmjs.com/package/mysql</a></p>
<p>安装：</p>
<div class="hljs"><pre><code class="hljs shell">npm install --save  mysql</code></pre></div>

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 引入mysql包</span>
<span class="hljs-keyword">var</span> mysql      = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;mysql&#x27;</span>);

<span class="hljs-comment">// 创建连接</span>
<span class="hljs-keyword">var</span> connection = mysql.createConnection(&#123;
  host     : <span class="hljs-string">&#x27;localhost&#x27;</span>,	<span class="hljs-comment">//本机</span>
  user     : <span class="hljs-string">&#x27;me&#x27;</span>,		<span class="hljs-comment">//账号root</span>
  password : <span class="hljs-string">&#x27;secret&#x27;</span>,	<span class="hljs-comment">//密码12345</span>
  database : <span class="hljs-string">&#x27;my_db&#x27;</span>	<span class="hljs-comment">//数据库名</span>
&#125;);
 
<span class="hljs-comment">// 连接数据库	（打开冰箱门）</span>
connection.connect();
 
<span class="hljs-comment">//执行数据操作	（把大象放到冰箱）</span>
connection.query(<span class="hljs-string">&#x27;SELECT * FROM `users` &#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, results, fields</span>) </span>&#123;
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;<span class="hljs-comment">//抛出异常阻止代码往下执行</span>
  <span class="hljs-comment">// 没有异常打印输出结果</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;The solution is: &#x27;</span>,results);
&#125;);

<span class="hljs-comment">//关闭连接	（关闭冰箱门）</span>
connection.end();</code></pre></div>





<h1 id="异步编程"><a href="#异步编程" class="headerlink" title="异步编程"></a>异步编程</h1><h2 id="回调函数"><a href="#回调函数" class="headerlink" title="回调函数"></a>回调函数</h2><p>不成立的情况下：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">x,y</span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">1</span>);
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        <span class="hljs-built_in">console</span>.log(<span class="hljs-number">2</span>);
        <span class="hljs-keyword">var</span> ret = x + y;
        <span class="hljs-keyword">return</span> ret;
    &#125;,<span class="hljs-number">1000</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">3</span>);
    <span class="hljs-comment">//到这里执行就结束了，不会i等到前面的定时器，所以直接返回了默认值 undefined</span>
&#125;

<span class="hljs-built_in">console</span>.log(add(<span class="hljs-number">2</span>,<span class="hljs-number">2</span>));
<span class="hljs-comment">// 结果是 1 3 undefined 4</span></code></pre></div>

<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200313085008929.png" srcset="/img/loading.gif" alt="image-20200313085008929"></p>
<p>使用回调函数解决：</p>
<p>回调函数：通过一个函数，获取函数内部的操作。（根据输入得到输出结果）</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> ret;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">x,y,callback</span>)</span>&#123;
    <span class="hljs-comment">// callback就是回调函数</span>
    <span class="hljs-comment">// var x = 10;</span>
    <span class="hljs-comment">// var y = 20;</span>
    <span class="hljs-comment">// var callback = function(ret)&#123;console.log(ret);&#125;</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">1</span>);
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        <span class="hljs-keyword">var</span> ret = x + y;
        callback(ret);
    &#125;,<span class="hljs-number">1000</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">3</span>);
&#125;
add(<span class="hljs-number">10</span>,<span class="hljs-number">20</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">ret</span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(ret);
&#125;);</code></pre></div>

<img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200313084746701.png" srcset="/img/loading.gif" alt="image-20200313084746701" style="zoom:100%;" />

<p>注意：</p>
<p>​    凡是需要得到一个函数内部异步操作的结果（setTimeout,readFile,writeFile,ajax,readdir）</p>
<p>​    这种情况必须通过   回调函数 (异步API都会伴随着一个回调函数)</p>
<p>ajax:</p>
<p>基于原生XMLHttpRequest封装get方法：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> oReq = <span class="hljs-keyword">new</span> XMLHttpRequest();
<span class="hljs-comment">// 当请求加载成功要调用指定的函数</span>
oReq.onload = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(oReq.responseText);
&#125;
oReq.open(<span class="hljs-string">&quot;GET&quot;</span>, <span class="hljs-string">&quot;请求路径&quot;</span>,<span class="hljs-literal">true</span>);
oReq.send();</code></pre></div>

<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get</span>(<span class="hljs-params">url,callback</span>)</span>&#123;
    <span class="hljs-keyword">var</span> oReq = <span class="hljs-keyword">new</span> XMLHttpRequest();
    <span class="hljs-comment">// 当请求加载成功要调用指定的函数</span>
    oReq.onload = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        <span class="hljs-comment">//console.log(oReq.responseText);</span>
        callback(oReq.responseText);
    &#125;
    oReq.open(<span class="hljs-string">&quot;GET&quot;</span>, url,<span class="hljs-literal">true</span>);
    oReq.send();
&#125;
get(<span class="hljs-string">&#x27;data.json&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(data);
&#125;);</code></pre></div>

<h2 id="Promise"><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h2><p>callback  hell（回调地狱）:</p>
<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314143410972.png" srcset="/img/loading.gif" alt="image-20200314143410972"></p>
<p>文件的读取无法判断执行顺序（文件的执行顺序是依据文件的大小来决定的）(异步api无法保证文件的执行顺序)</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);

fs.readFile(<span class="hljs-string">&#x27;./data/a.text&#x27;</span>,<span class="hljs-string">&#x27;utf8&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
	<span class="hljs-keyword">if</span>(err)&#123;
		<span class="hljs-comment">// 1 读取失败直接打印输出读取失败</span>
		<span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;读取失败&#x27;</span>);
		<span class="hljs-comment">// 2 抛出异常</span>
		<span class="hljs-comment">// 		阻止程序的执行</span>
		<span class="hljs-comment">// 		把错误信息打印到控制台</span>
		<span class="hljs-keyword">throw</span> err;
	&#125;
	<span class="hljs-built_in">console</span>.log(data);
&#125;);

fs.readFile(<span class="hljs-string">&#x27;./data/b.text&#x27;</span>,<span class="hljs-string">&#x27;utf8&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
	<span class="hljs-keyword">if</span>(err)&#123;
		<span class="hljs-comment">// 1 读取失败直接打印输出读取失败</span>
		<span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;读取失败&#x27;</span>);
		<span class="hljs-comment">// 2 抛出异常</span>
		<span class="hljs-comment">// 		阻止程序的执行</span>
		<span class="hljs-comment">// 		把错误信息打印到控制台</span>
		<span class="hljs-keyword">throw</span> err;
	&#125;
	<span class="hljs-built_in">console</span>.log(data);
&#125;);</code></pre></div>

<p>通过回调嵌套的方式来保证顺序：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);

fs.readFile(<span class="hljs-string">&#x27;./data/a.text&#x27;</span>,<span class="hljs-string">&#x27;utf8&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
	<span class="hljs-keyword">if</span>(err)&#123;
		<span class="hljs-comment">// 1 读取失败直接打印输出读取失败</span>
		<span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;读取失败&#x27;</span>);
		<span class="hljs-comment">// 2 抛出异常</span>
		<span class="hljs-comment">// 		阻止程序的执行</span>
		<span class="hljs-comment">// 		把错误信息打印到控制台</span>
		<span class="hljs-keyword">throw</span> err;
	&#125;
	<span class="hljs-built_in">console</span>.log(data);
	fs.readFile(<span class="hljs-string">&#x27;./data/b.text&#x27;</span>,<span class="hljs-string">&#x27;utf8&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
		<span class="hljs-keyword">if</span>(err)&#123;
			<span class="hljs-comment">// 1 读取失败直接打印输出读取失败</span>
			<span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;读取失败&#x27;</span>);
			<span class="hljs-comment">// 2 抛出异常</span>
			<span class="hljs-comment">// 		阻止程序的执行</span>
			<span class="hljs-comment">// 		把错误信息打印到控制台</span>
			<span class="hljs-keyword">throw</span> err;
		&#125;
		<span class="hljs-built_in">console</span>.log(data);
		fs.readFile(<span class="hljs-string">&#x27;./data/a.text&#x27;</span>,<span class="hljs-string">&#x27;utf8&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,data</span>)</span>&#123;
			<span class="hljs-keyword">if</span>(err)&#123;
				<span class="hljs-comment">// 1 读取失败直接打印输出读取失败</span>
				<span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;读取失败&#x27;</span>);
				<span class="hljs-comment">// 2 抛出异常</span>
				<span class="hljs-comment">// 		阻止程序的执行</span>
				<span class="hljs-comment">// 		把错误信息打印到控制台</span>
				<span class="hljs-keyword">throw</span> err;
			&#125;
			<span class="hljs-built_in">console</span>.log(data);
		&#125;);
	&#125;);
&#125;);</code></pre></div>

<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314144807008.png" srcset="/img/loading.gif" alt="image-20200314144807008">为了解决以上编码方式带来的问题（回调地狱嵌套），所以在EcmaScript6新增了一个API:<code>Promise</code>。<img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314150050839.png" srcset="/img/loading.gif" alt="image-20200314150050839"></p>
<ul>
<li>Promise：承诺，保证</li>
<li>Promise本身不是异步的，但往往都是内部封装一个异步任务</li>
</ul>
<p>基本语法：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 在EcmaScript 6中新增了一个API Promise</span>
<span class="hljs-comment">// Promise 是一个构造函数</span>

<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);
<span class="hljs-comment">// 1 创建Promise容器		resolve:解决   reject：失败</span>
<span class="hljs-keyword">var</span> p1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>&#123;
	fs.readFile(<span class="hljs-string">&#x27;./a.text&#x27;</span>, <span class="hljs-string">&#x27;utf8&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, data</span>) </span>&#123;
		<span class="hljs-keyword">if</span> (err) &#123;
			<span class="hljs-comment">// console.log(err);</span>
			<span class="hljs-comment">// 把容器的Pending状态变为rejected</span>
			reject(err);
		&#125; <span class="hljs-keyword">else</span> &#123;
			<span class="hljs-comment">// console.log(data);</span>
			<span class="hljs-comment">// 把容器的Pending状态变为resolve</span>
			resolve(<span class="hljs-number">1234</span>);
		&#125;
	&#125;);
&#125;);

<span class="hljs-comment">// 当p1成功了，然后就（then）做指定的操作</span>
<span class="hljs-comment">// then方法接收的function就是容器中的resolve函数</span>
p1
	.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>&#123;
		<span class="hljs-built_in">console</span>.log(data);
	&#125;, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err</span>) </span>&#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;读取文件失败了&#x27;</span>, err);
	&#125;);
</code></pre></div>

<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200315100611620.png" srcset="/img/loading.gif" alt="image-20200315100611620"></p>
<p>链式循环：<img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200315125559136.png" srcset="/img/loading.gif" alt="image-20200315125559136"></p>
<p>封装Promise的<code>readFile</code>：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pReadFile</span>(<span class="hljs-params">filePath</span>) </span>&#123;
	<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resolve, reject</span>) </span>&#123;
		fs.readFile(filePath, <span class="hljs-string">&#x27;utf8&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, data</span>) </span>&#123;
			<span class="hljs-keyword">if</span> (err) &#123;
				reject(err);
			&#125; <span class="hljs-keyword">else</span> &#123;
				resolve(data);
			&#125;
		&#125;);
	&#125;);
&#125;

pReadFile(<span class="hljs-string">&#x27;./a.txt&#x27;</span>)
	.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>&#123;
		<span class="hljs-built_in">console</span>.log(data);
		<span class="hljs-keyword">return</span> pReadFile(<span class="hljs-string">&#x27;./b.txt&#x27;</span>);
	&#125;)
	.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>&#123;
		<span class="hljs-built_in">console</span>.log(data);
		<span class="hljs-keyword">return</span> pReadFile(<span class="hljs-string">&#x27;./a.txt&#x27;</span>);
	&#125;)
	.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>&#123;
		<span class="hljs-built_in">console</span>.log(data);
	&#125;)
</code></pre></div>

<p>mongoose所有的API都支持Promise：</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-comment">// 查询所有</span>
User.find()
	.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>)</span>&#123;
        <span class="hljs-built_in">console</span>.log(data)
    &#125;)</code></pre></div>

<p>注册：</p>
<div class="hljs"><pre><code class="hljs javascript">User.findOne(&#123;<span class="hljs-attr">username</span>:<span class="hljs-string">&#x27;admin&#x27;</span>&#125;,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">user</span>)</span>&#123;
    <span class="hljs-keyword">if</span>(user)&#123;
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;用户已存在&#x27;</span>)
    &#125; <span class="hljs-keyword">else</span> &#123;
        <span class="hljs-keyword">new</span> User(&#123;
             username:<span class="hljs-string">&#x27;aaa&#x27;</span>,
             password:<span class="hljs-string">&#x27;123&#x27;</span>,
             email:<span class="hljs-string">&#x27;fffff&#x27;</span>
        &#125;).save(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;注册成功&#x27;</span>);
        &#125;)
    &#125;
&#125;)</code></pre></div>



<div class="hljs"><pre><code class="hljs javascript">User.findOne(&#123;
    username:<span class="hljs-string">&#x27;admin&#x27;</span>
&#125;)
    .then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">user</span>)</span>&#123;
        <span class="hljs-keyword">if</span>(user)&#123;
            <span class="hljs-comment">// 用户已经存在不能注册</span>
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;用户已存在&#x27;</span>);
        &#125;
        <span class="hljs-keyword">else</span>&#123;
            <span class="hljs-comment">// 用户不存在可以注册</span>
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> User(&#123;
                username:<span class="hljs-string">&#x27;aaa&#x27;</span>,
                password:<span class="hljs-string">&#x27;123&#x27;</span>,
                email:<span class="hljs-string">&#x27;fffff&#x27;</span>
            &#125;).save();
        &#125;
    &#125;)
    .then(funciton(ret)&#123;
		<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;注册成功&#x27;</span>);
    &#125;)</code></pre></div>



<h2 id="Generator"><a href="#Generator" class="headerlink" title="Generator"></a>Generator</h2><p>async函数</p>
<h1 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h1><h2 id="修改完代码自动重启"><a href="#修改完代码自动重启" class="headerlink" title="修改完代码自动重启"></a>修改完代码自动重启</h2><p>我们在这里可以使用一个第三方命名行工具：<code>nodemon</code>来帮助我们解决频繁修改代码重启服务器的问题。</p>
<p><code>nodemon</code>是一个基于Node.js开发的一个第三方命令行工具，我们使用的时候需要独立安装：</p>
<div class="hljs"><pre><code class="hljs javascript">#在任意目录执行该命令都可以
#也就是说，所有需要 --global安装的包都可以在任意目录执行
npm install --<span class="hljs-built_in">global</span> nodemon
npm install -g nodemon

#如果安装不成功的话，可以使用cnpm安装
cnpm install -g nodemon</code></pre></div>

<p>安装完毕之后使用：</p>
<div class="hljs"><pre><code class="hljs javascript">node app.js

#使用nodemon
nodemon app.js</code></pre></div>

<p>只要是通过<code>nodemon</code>启动的服务，则他会监视你的文件变化，当文件发生变化的时候，会自动帮你重启服务器。</p>
<h2 id="封装异步API"><a href="#封装异步API" class="headerlink" title="封装异步API"></a>封装异步API</h2><p>回调函数：获取异步操作的结果</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fn</span>(<span class="hljs-params">callback</span>)</span>&#123;
    <span class="hljs-comment">// var callback = funtion(data)&#123; console.log(data); &#125;</span>
	<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
        <span class="hljs-keyword">var</span> data = <span class="hljs-string">&#x27;hello&#x27;</span>;
        callback(data);
    &#125;,<span class="hljs-number">1000</span>);
&#125;
<span class="hljs-comment">// 如果需要获取一个函数中异步操作的结果，则必须通过回调函数的方式来获取</span>
fn(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(data);
&#125;)</code></pre></div>

<h2 id="数组的遍历方法，都是对函数作为一种参数"><a href="#数组的遍历方法，都是对函数作为一种参数" class="headerlink" title="数组的遍历方法，都是对函数作为一种参数"></a>数组的遍历方法，都是对函数作为一种参数</h2><p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200314094620191.png" srcset="/img/loading.gif" alt="image-20200314094620191"></p>
<h2 id="EcmaScript-6"><a href="#EcmaScript-6" class="headerlink" title="EcmaScript 6"></a>EcmaScript 6</h2><blockquote>
<p>参考文档：<a target="_blank" rel="noopener" href="https://es6.ruanyifeng.com/">https://es6.ruanyifeng.com/</a></p>
</blockquote>
<h1 id="项目案例"><a href="#项目案例" class="headerlink" title="项目案例"></a>项目案例</h1><h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><div class="hljs"><pre><code class="hljs javascript">.
app.js	项目的入口文件
controllers
models	存储使用mongoose设计的数据模型
node_modules	第三方包
package.json	包描述文件
package-lock.json	第三方包版本锁定文件（npm5之后才有）
public	公共静态资源
routes
views	存储视图目录</code></pre></div>

<h2 id="模板页"><a href="#模板页" class="headerlink" title="模板页"></a>模板页</h2><ul>
<li>子模板</li>
<li>模板继承</li>
</ul>
<h2 id="路由设计-1"><a href="#路由设计-1" class="headerlink" title="路由设计"></a>路由设计</h2><table>
<thead>
<tr>
<th>路由</th>
<th>方法</th>
<th>get参数</th>
<th>post参数</th>
<th>是否需要登录</th>
<th>备注</th>
</tr>
</thead>
<tbody><tr>
<td>/</td>
<td>get</td>
<td></td>
<td></td>
<td></td>
<td>渲染首页</td>
</tr>
<tr>
<td>/register(登录)</td>
<td>get</td>
<td></td>
<td></td>
<td></td>
<td>渲染注册页面</td>
</tr>
<tr>
<td>/register</td>
<td>post</td>
<td></td>
<td>email,nickname,password</td>
<td></td>
<td>处理注册请求</td>
</tr>
<tr>
<td>/login</td>
<td>get</td>
<td></td>
<td></td>
<td></td>
<td>渲染登陆界面</td>
</tr>
<tr>
<td>/login</td>
<td>post</td>
<td></td>
<td>email,password</td>
<td></td>
<td>处理登录请求</td>
</tr>
<tr>
<td>/loginout</td>
<td>get</td>
<td></td>
<td></td>
<td></td>
<td>处理退出请求</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h2 id="模型设计"><a href="#模型设计" class="headerlink" title="模型设计"></a>模型设计</h2><h2 id="功能实现"><a href="#功能实现" class="headerlink" title="功能实现"></a>功能实现</h2><h2 id="步骤-1"><a href="#步骤-1" class="headerlink" title="步骤"></a>步骤</h2><ul>
<li>创建目录结构</li>
<li>整合静态也-模板页<ul>
<li>include</li>
<li>block</li>
<li>extend</li>
</ul>
</li>
<li>设计用户登陆，退出，注册的路由</li>
<li>用户注册<ul>
<li>先处理客户端页面的内容（表单控件的name，收集表单数据，发起请求）</li>
<li>服务端<ul>
<li>获取从客户端收到的数据</li>
<li>操作数据库<ul>
<li>如果有错，发送500告诉客户端服务器错了‘</li>
<li>其他的根据业务发送不同的响应数据</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>登录</li>
<li>退出</li>
</ul>
<h1 id="Express中间件"><a href="#Express中间件" class="headerlink" title="Express中间件"></a>Express中间件</h1><h2 id="中间件的概念"><a href="#中间件的概念" class="headerlink" title="中间件的概念"></a>中间件的概念</h2><blockquote>
<p>参考文档：<a target="_blank" rel="noopener" href="http://expressjs.com/en/guide/using-middleware.html">http://expressjs.com/en/guide/using-middleware.html</a></p>
</blockquote>
<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200316202757617.png" srcset="/img/loading.gif" alt="image-20200316202757617"></p>
<p>中间件：把很复杂的事情分割成单个，然后依次有条理的执行。就是一个中间处理环节，有输入，有输出。</p>
<p>说的通俗易懂点儿，中间件就是一个（从请求到响应调用的方法）方法。</p>
<p>把数据从请求到响应分步骤来处理，每一个步骤都是一个中间处理环节。</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;http&#x27;</span>);
<span class="hljs-keyword">var</span> url = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;url&#x27;</span>);

<span class="hljs-keyword">var</span> cookie = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./expressPtoject/cookie&#x27;</span>);
<span class="hljs-keyword">var</span> query = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./expressPtoject/query&#x27;</span>);
<span class="hljs-keyword">var</span> postBody = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./expressPtoject/post-body&#x27;</span>);

<span class="hljs-keyword">var</span> server = http.createServer(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
	<span class="hljs-comment">// 解析请求地址中的get参数</span>
	<span class="hljs-comment">// var obj = url.parse(req.url,true);</span>
	<span class="hljs-comment">// req.query = obj.query;</span>
	query(req,res);	<span class="hljs-comment">//中间件</span>
	
	<span class="hljs-comment">// 解析请求地址中的post参数</span>
	req.body = &#123;
		foo:<span class="hljs-string">&#x27;bar&#x27;</span>
	&#125;
&#125;);

<span class="hljs-keyword">if</span>(req.url === <span class="hljs-string">&#x27;xxx&#x27;</span>)&#123;
	<span class="hljs-comment">// 处理请求</span>
	...
&#125;

server.listen(<span class="hljs-number">3000</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;3000 runing...&#x27;</span>);
&#125;);</code></pre></div>

<p>同一个请求对象所经过的中间件都是同一个请求对象和响应对象。</p>
<div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>);
<span class="hljs-keyword">var</span> app = express();
app.get(<span class="hljs-string">&#x27;/abc&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>)</span>&#123;
	<span class="hljs-comment">// 同一个请求的req和res是一样的，</span>
	<span class="hljs-comment">// 可以前面存储下面调用</span>
	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;/abc&#x27;</span>);
	<span class="hljs-comment">// req.foo = &#x27;bar&#x27;;</span>
	req.body = &#123;
		name:<span class="hljs-string">&#x27;xiaoxiao&#x27;</span>,
		age:<span class="hljs-number">18</span>
	&#125;
	next();
&#125;);
app.get(<span class="hljs-string">&#x27;/abc&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>)</span>&#123;
	<span class="hljs-comment">// console.log(req.foo);</span>
	<span class="hljs-built_in">console</span>.log(req.body);
	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;/abc&#x27;</span>);
&#125;);
app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>&#123;
	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;app is running at port 3000.&#x27;</span>);
&#125;);
</code></pre></div>

<p><img src="C:\Users\A\AppData\Roaming\Typora\typora-user-images\image-20200317110520098.png" srcset="/img/loading.gif" alt="image-20200317110520098"></p>
<h2 id="中间件的分类"><a href="#中间件的分类" class="headerlink" title="中间件的分类:"></a>中间件的分类:</h2><h3 id="应用程序级别的中间件"><a href="#应用程序级别的中间件" class="headerlink" title="应用程序级别的中间件"></a>应用程序级别的中间件</h3><p>万能匹配（不关心任何请求路径和请求方法的中间件）：</p>
<div class="hljs"><pre><code class="hljs javascript">app.use(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;Time&#x27;</span>,<span class="hljs-built_in">Date</span>.now());
    next();
&#125;);</code></pre></div>

<p>关心请求路径和请求方法的中间件：</p>
<div class="hljs"><pre><code class="hljs javascript">app.use(<span class="hljs-string">&#x27;/a&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>)</span>&#123;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;Time&#x27;</span>,<span class="hljs-built_in">Date</span>.now());
    next();
&#125;);</code></pre></div>

<h3 id="路由级别的中间件"><a href="#路由级别的中间件" class="headerlink" title="路由级别的中间件"></a>路由级别的中间件</h3><p>严格匹配请求路径和请求方法的中间件</p>
<p>get:</p>
<div class="hljs"><pre><code class="hljs javascript">app.get(<span class="hljs-string">&#x27;/&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
	res.send(<span class="hljs-string">&#x27;get&#x27;</span>);
&#125;);</code></pre></div>

<p>post：</p>
<div class="hljs"><pre><code class="hljs javascript">app.post(<span class="hljs-string">&#x27;/a&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
	res.send(<span class="hljs-string">&#x27;post&#x27;</span>);
&#125;);</code></pre></div>

<p>put:</p>
<div class="hljs"><pre><code class="hljs javascript">app.put(<span class="hljs-string">&#x27;/user&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
	res.send(<span class="hljs-string">&#x27;put&#x27;</span>);
&#125;);</code></pre></div>

<p>delete:</p>
<div class="hljs"><pre><code class="hljs javascript">app.delete(<span class="hljs-string">&#x27;/delete&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
	res.send(<span class="hljs-string">&#x27;delete&#x27;</span>);
&#125;);</code></pre></div>

<h3 id="总"><a href="#总" class="headerlink" title="总"></a>总</h3><div class="hljs"><pre><code class="hljs javascript"><span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>);
<span class="hljs-keyword">var</span> app = express();

<span class="hljs-comment">// 中间件：处理请求，本质就是个函数</span>
<span class="hljs-comment">// 在express中，对中间件有几种分类</span>

<span class="hljs-comment">// 1 不关心任何请求路径和请求方法的中间件</span>
<span class="hljs-comment">// 也就是说任何请求都会进入这个中间件</span>
<span class="hljs-comment">// 中间件本身是一个方法，该方法接收三个参数</span>
<span class="hljs-comment">// Request 请求对象</span>
<span class="hljs-comment">// Response 响应对象</span>
<span class="hljs-comment">// next 下一个中间件</span>
<span class="hljs-comment">// // 全局匹配中间件</span>
<span class="hljs-comment">// app.use(function(req, res, next) &#123;</span>
<span class="hljs-comment">// 	console.log(&#x27;1&#x27;);</span>
<span class="hljs-comment">// 	// 当一个请求进入中间件后</span>
<span class="hljs-comment">// 	// 如果需要请求另外一个方法则需要使用next（）方法</span>
<span class="hljs-comment">// 	next();</span>
<span class="hljs-comment">// 	// next是一个方法，用来调用下一个中间件</span>
<span class="hljs-comment">//  // 注意：next（）方法调用下一个方法的时候，也会匹配（不是调用紧挨着的哪一个）</span>
<span class="hljs-comment">// &#125;);</span>
<span class="hljs-comment">// app.use(function(req, res, next) &#123;</span>
<span class="hljs-comment">// 	console.log(&#x27;2&#x27;);</span>
<span class="hljs-comment">// &#125;);</span>

<span class="hljs-comment">// // 2 关心请求路径的中间件</span>
<span class="hljs-comment">// // 以/xxx开头的中间件</span>
<span class="hljs-comment">// app.use(&#x27;/a&#x27;,function(req, res, next) &#123;</span>
<span class="hljs-comment">// 	console.log(req.url);</span>
<span class="hljs-comment">// &#125;);</span>

<span class="hljs-comment">// 3 严格匹配请求方法和请求路径的中间件</span>
app.get(<span class="hljs-string">&#x27;/&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;/&#x27;</span>);
&#125;);
app.post(<span class="hljs-string">&#x27;/a&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>&#123;
	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;/a&#x27;</span>);
&#125;);

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>&#123;
	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;app is running at port 3000.&#x27;</span>);
&#125;);
</code></pre></div>

<h2 id="错误处理中间件"><a href="#错误处理中间件" class="headerlink" title="错误处理中间件"></a>错误处理中间件</h2><div class="hljs"><pre><code class="hljs javascript">app.use(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,req,res,next</span>)</span>&#123;
    <span class="hljs-built_in">console</span>.error(err,stack);
    res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">&#x27;Something broke&#x27;</span>);
&#125;);</code></pre></div>

<p>配置使用404中间件：</p>
<div class="hljs"><pre><code class="hljs javascript">app.use(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res</span>)</span>&#123;
    res.render(<span class="hljs-string">&#x27;404.html&#x27;</span>);
&#125;);</code></pre></div>

<p>配置全局错误处理中间件:</p>
<div class="hljs"><pre><code class="hljs javascript">app.get(<span class="hljs-string">&#x27;/a&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res, next</span>) </span>&#123;
	fs.readFile(<span class="hljs-string">&#x27;.a/bc&#x27;</span>, funtion() &#123;
		<span class="hljs-keyword">if</span> (err) &#123;
        	<span class="hljs-comment">// 当调用next()传参后，则直接进入到全局错误处理中间件方法中</span>
        	<span class="hljs-comment">// 当发生全局错误的时候，我们可以调用next传递错误对象</span>
        	<span class="hljs-comment">// 然后被全局错误处理中间件匹配到并进行处理</span>
			next(err);
		&#125;
	&#125;)
&#125;);
<span class="hljs-comment">//全局错误处理中间件</span>
app.use(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err,req,res,next</span>)</span>&#123;
    res.status(<span class="hljs-number">500</span>).json(&#123;
        err_code:<span class="hljs-number">500</span>,
        message:err.message
    &#125;);
&#125;);</code></pre></div>





<h2 id="内置中间件"><a href="#内置中间件" class="headerlink" title="内置中间件"></a>内置中间件</h2><ul>
<li>express.static(提供静态文件)<ul>
<li><a target="_blank" rel="noopener" href="http://expressjs.com/en/starter/static-files.html#serving-static-files-in-express">http://expressjs.com/en/starter/static-files.html#serving-static-files-in-express</a></li>
</ul>
</li>
</ul>
<h2 id="第三方中间件"><a href="#第三方中间件" class="headerlink" title="第三方中间件"></a>第三方中间件</h2><blockquote>
<p>参考文档：<a target="_blank" rel="noopener" href="http://expressjs.com/en/resources/middleware.html">http://expressjs.com/en/resources/middleware.html</a></p>
</blockquote>
<ul>
<li>body-parser</li>
<li>compression</li>
<li>cookie-parser</li>
<li>mogran</li>
<li>response-time</li>
<li>server-static</li>
<li>session</li>
</ul>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                <div class="post-meta mr-3">
                  <i class="iconfont icon-category"></i>
                  
                  <a class="hover-with-bg" href="/categories/Nodejs/">Nodejs</a>
                  
                </div>
                
                
                <div class="post-meta">
                  <i class="iconfont icon-tags"></i>
                  
                  <a class="hover-with-bg" href="/tags/mongoose/">mongoose</a>
                  
                  <a class="hover-with-bg" href="/tags/promise/">promise</a>
                  
                  <a class="hover-with-bg" href="/tags/es6/">es6</a>
                  
                  <a class="hover-with-bg" href="/tags/node/">node</a>
                  
                  <a class="hover-with-bg" href="/tags/express/">express</a>
                  
                  <a class="hover-with-bg" href="/tags/body-parse/">body-parse</a>
                  
                </div>
                
              </div>
              
              
              <div class="post-prevnext row">
                <article class="post-prev col-6">
                  
                  
                  <a href="/2020/08/22/12-SVN/">
                    <i class="iconfont icon-arrowleft"></i>
                    <span class="hidden-mobile">SVN</span>
                    <span class="visible-mobile">上一篇</span>
                  </a>
                  
                </article>
                <article class="post-next col-6">
                  
                  
                  <a href="/2020/08/12/10.promise/">
                    <span class="hidden-mobile">回调地狱（callback hell） 和 promise</span>
                    <span class="visible-mobile">下一篇</span>
                    <i class="iconfont icon-arrowright"></i>
                  </a>
                  
                </article>
              </div>
              
            </div>

            
            <!-- Comments -->
            <article class="comments" id="comments">
              
              
  <div id="vcomments"></div>
  <script type="text/javascript">
    function loadValine() {
      addScript('https://cdn.staticfile.org/valine/1.4.14/Valine.min.js', function () {
        new Valine({
          el: "#vcomments",
          app_id: "hjxsDRXYScicliqD8I8JqoTu-gzGzoHsz",
          app_key: "qUcAEReEqeEVp5wwXJ41uCCp",
          placeholder: "说点什么",
          path: window.location.pathname,
          avatar: "retro",
          meta: ["nick","mail","link"],
          pageSize: "10",
          lang: "zh-CN",
          highlight: true,
          recordIP: false,
          serverURLs: "",
        });
      });
    }
    waitElementVisible('vcomments', loadValine);
  </script>
  <noscript>Please enable JavaScript to view the <a target="_blank" href="https://valine.js.org" rel="nofollow noopener noopener">comments
      powered by Valine.</a></noscript>


            </article>
            
          </article>
        </div>
      </div>
    </div>
    
    <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
      <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

    </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  

  <footer class="mt-5">
  <div class="text-center py-3">
    <div>
      <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a>
      <i class="iconfont icon-love"></i>
      <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener">
        <span>Fluid</span></a>
    </div>
    
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


    

    
  </div>
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/js/debouncer.js" ></script>
<script  src="/js/main.js" ></script>

<!-- Plugins -->


  
    
      <script  src="/js/lazyload.js" ></script>
    
  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/js/clipboard-use.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '#post-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "Node基础总结&nbsp;",
      ],
      cursorChar: "_",
      typeSpeed: 70,
      loop: false,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "always",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/js/local-search.js" ></script>
  <script>
    var path = "/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>







  
  
    <script>
      !function (e, t, a) {
        function r() {
          for (var e = 0; e < s.length; e++) s[e].alpha <= 0 ? (t.body.removeChild(s[e].el), s.splice(e, 1)) : (s[e].y--, s[e].scale += .004, s[e].alpha -= .013, s[e].el.style.cssText = "left:" + s[e].x + "px;top:" + s[e].y + "px;opacity:" + s[e].alpha + ";transform:scale(" + s[e].scale + "," + s[e].scale + ") rotate(45deg);background:" + s[e].color + ";z-index:99999");
          requestAnimationFrame(r)
        }

        function n() {
          var t = "function" == typeof e.onclick && e.onclick;
          e.onclick = function (e) {
            t && t(), o(e)
          }
        }

        function o(e) {
          var a = t.createElement("div");
          a.className = "heart", s.push({
            el: a,
            x: e.clientX - 5,
            y: e.clientY - 5,
            scale: 1,
            alpha: 1,
            color: c()
          }), t.body.appendChild(a)
        }

        function i(e) {
          var a = t.createElement("style");
          a.type = "text/css";
          try {
            a.appendChild(t.createTextNode(e))
          } catch (t) {
            a.styleSheet.cssText = e
          }
          t.getElementsByTagName("head")[0].appendChild(a)
        }

        function c() {
          return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")"
        }

        var s = [];
        e.requestAnimationFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (e) {
          setTimeout(e, 1e3 / 60)
        }, i(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"), n(), r()
      }(window, document);
    </script>
  











  

  

  

  

  

  





</body>
</html>
